#!/usr/bin/env perl
use strict;
use warnings;
use 5.020;
no autovivification warn => qw(fetch store exists delete);
use if "$]" >= 5.022, experimental => 're_strict';
no if "$]" >= 5.031009, feature => 'indirect';
no if "$]" >= 5.033001, feature => 'multidimensional';
no if "$]" >= 5.033006, feature => 'bareword_filehandles';
use Path::Tiny;
use HTTP::Tiny;
use YAML::PP;
use Digest::MD5 'md5_hex';
use JSON::Schema::Modern;

# note: the latest versions can always be found at https://spec.openapis.org/
# Once /latest links exist, we will pull from those instead, and use those names in code to ensure
# we always use the latest files.

# see https://spec.openapis.org/#openapi-specification-schemas for the latest links

my %files = (
  # metaschema for json schemas contained within openapi documents
  'oas/dialect/base.schema.json' => 'https://spec.openapis.org/oas/3.1/dialect/2024-10-25',

  # vocabulary definition
  'oas/meta/base.schema.json' => 'https://spec.openapis.org/oas/3.1/meta/2024-10-25',

  # openapi document schema + custom json schema dialect
  'oas/schema-base.json' => 'https://spec.openapis.org/oas/3.1/schema-base/2024-11-14',

  # the main openapi document schema
  'oas/schema.json' => 'https://spec.openapis.org/oas/3.1/schema/2024-11-14',

  'oas/LICENSE' => 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/LICENSE',
);

my %checksums;

foreach my $target (keys %files) {
  my $source = $files{$target};
  $target = path('share', $target);
  $target->parent->mkpath;

  my $response = HTTP::Tiny->new->get($source);
  die "Failed to fetch $source: $response->{status} $response->{reason}" if not $response->{success};

  $target->spew_raw($response->{content});
  $checksums{$target} = md5_hex($response->{content});
}

# compute checksums and record them in the test
path('t/checksums.t')->edit_raw(sub {
  m/^__DATA__$/mg;
  $_ = substr($_, 0, pos()+1).join("\n", map $_.' '.$checksums{$_}, sort keys %checksums)."\n";
});

my $yaml = YAML::PP->new(boolean => 'JSON::PP');
my $js = JSON::Schema::Modern->new(validate_formats => 1);
$js->add_schema($files{$_} => $yaml->load_file('share/'.$_)) foreach grep /json$/, keys %files;

foreach my $uri (values %files) {
  next if $uri =~ /LICENSE$/;
  print "# validating $uri\n" if $ENV{DEBUG};

  my $document = $js->_fetch_from_uri($uri)->{document};
  my $result = $js->evaluate($document->schema, $document->metaschema_uri);

  die $js->_json_decoder->pretty->encode($result) if not $result->valid;
}
