use strict;
use warnings;
use lib qw(./lib ../lib t/lib);
use FindBin qw($Bin);
use File::Spec::Functions qw(catfile);
use JSON::XS;
use Test::More;
use Test::ConvertPheno qw(load_json_file run_command_capture);

my $script = catfile( $Bin, '..', 'api', 'perl', 'json_bridge.pl' );
my $json   = JSON::XS->new->canonical;

sub run_bridge {
    my ($payload) = @_;
    return run_command_capture(
        command => [ $^X, $script ],
        stdin   => $payload,
    );
}

my ( $exit_ok, $stdout_ok, $stderr_ok ) = run_bridge(
    $json->encode(
        {
            method => 'pxf2bff',
            data   => {
                phenopacket => {
                    id      => 'P0007500',
                    subject => {
                        id          => 'P0007500',
                        dateOfBirth => 'unknown-01-01T00:00:00Z',
                        sex         => 'FEMALE'
                    }
                }
            }
        }
    )
);

is( $exit_ok, 0, 'bridge exits successfully for valid payload' );
is( $stderr_ok, q{}, 'bridge keeps stderr empty on success' );

my $decoded = eval { $json->decode($stdout_ok) };
ok( !$@, 'bridge returns valid JSON on success' );
is( $decoded->{id}, 'P0007500', 'bridge returns converted BFF payload' );

my ( $exit_fhir, $stdout_fhir, $stderr_fhir ) = run_bridge(
    $json->encode(
        {
            method => 'fhir2bff',
            data   => load_json_file('t/fhir2bff/in/patient-bundle.json'),
            test   => 1,
        }
    )
);
is( $exit_fhir, 0, 'bridge accepts an in-memory FHIR Bundle' );
is( $stderr_fhir, q{}, 'FHIR bridge conversion keeps stderr empty' );
my $fhir = eval { $json->decode($stdout_fhir) };
is(
    $fhir->[0]{id},
    '5b24c87b-6223-f5b4-51e9-82051159bd1d',
    'Python bridge exposes fhir2bff'
);

my ( $exit_missing_method, undef, $stderr_missing_method ) =
  run_bridge( $json->encode( { data => {} } ) );
isnt( $exit_missing_method, 0, 'bridge fails when method is missing' );
like(
    $stderr_missing_method,
    qr/Payload must include string field 'method'/,
    'bridge reports missing method clearly'
);

my ( $exit_invalid_method, undef, $stderr_invalid_method ) =
  run_bridge( $json->encode( { method => 'not_a_method', data => {} } ) );
isnt( $exit_invalid_method, 0, 'bridge fails for invalid method name' );
like( $stderr_invalid_method, qr/not_a_method/, 'invalid method is reported' );

my ( $exit_internal_method, $stdout_internal_method, $stderr_internal_method ) =
  run_bridge( $json->encode( { method => 'get_info', data => {} } ) );
isnt( $exit_internal_method, 0, 'bridge rejects callable internal methods' );
is( $stdout_internal_method, q{}, 'bridge does not return internal method data' );
like(
    $stderr_internal_method,
    qr/Unsupported conversion <get_info>/,
    'bridge reports internal methods as unsupported conversions'
);

my ( $exit_bad_json, undef, $stderr_bad_json ) = run_bridge('{');
isnt( $exit_bad_json, 0, 'bridge fails for malformed JSON input' );
like( $stderr_bad_json, qr/Invalid JSON payload:/, 'malformed JSON is reported' );

done_testing;
