use Test2::V0;
use Test2::Harness::Util::JSON qw/encode_json decode_json/;
use Test2::Require::Module 'Test2::Plugin::Cover' => '0.000022';

use App::Yath::Tester qw/yath/;

use File::Temp qw/tempfile/;

my $dir = __FILE__;
$dir =~ s{\.t$}{}g;
$dir =~ s{^\./}{};
$dir =~ s/\d+$//;

my ($fh, $cfile) = tempfile(SUFFIX => '.jsonl');
close($fh);

yath(
    command => 'test',
    args    => ["-I$dir/lib", $dir, '--ext=tx', "--cover-write=$cfile", '-v'],
    exit    => 0,
);

my @coverage;
open($fh, '<', $cfile);
for my $line (<$fh>) {
    next unless $line;
    push @coverage => decode_json($line);
}

is(
    \@coverage,
    bag {
        item {
            'test'       => 't/integration/coverage/a.tx',
            'manager'    => 'Manager',
            'aggregator' => 'Test2::Harness::Log::CoverageAggregator::ByTest',
            'files'      => {
                'Ax.pm' => {
                    '*'  => ['*'],
                    'a'  => bag { item {'subtest' => 'b'}; item {'subtest' => 'c'}; item {'subtest' => 'a'} },
                    'aa' => [{'subtest' => 'a'}],
                },
                'Bx.pm' => {
                    'b' => bag { item {'subtest' => 'b'}; item {'subtest' => 'c'} },
                    '*' => ['*'],
                },
                'Cx.pm' => {
                    'c' => bag { item '*'; item {'subtest' => 'c'} },
                    '*' => ['*'],
                },
            },
        };

        item {
            'test'       => 't/integration/coverage/b.tx',
            'aggregator' => 'Test2::Harness::Log::CoverageAggregator::ByTest',
            'files'      => {
                'Bx.pm' => {
                    'b' => ['*'],
                    '*' => ['*'],
                },
            },
        };

        item {
            'test'       => 't/integration/coverage/c.tx',
            'manager'    => 'Manager',
            'aggregator' => 'Test2::Harness::Log::CoverageAggregator::ByTest',
            'files'      => {
                'Ax.pm' => {
                    'a' => bag { item {'subtest' => 'c'}; item {'subtest' => 'a'} },
                    '*' => [{'subtest' => 'a'}],
                },
                'Cx.pm' => {
                    'c' => [{'subtest' => 'c'}],
                    '*' => [{'subtest' => 'c'}],
                }
            }
        };

        item {
            'test'       => 't/integration/coverage/once.tx',
            'aggregator' => 'Test2::Harness::Log::CoverageAggregator::ByTest',
            'files'      => {},
        };

        item {
            'aggregator' => 'Test2::Harness::Log::CoverageAggregator::ByTest',
            'test'       => 't/integration/coverage/open.tx',
            'files'      => {'Bx.pm' => {'<>' => ['*']}},
        };

        item {
            'test'       => 't/integration/coverage/x.tx',
            'aggregator' => 'Test2::Harness::Log::CoverageAggregator::ByTest',
            'files'      => {'Bx.pm' => {'*' => ['*']}},
        };
    },
    "Got predicted coverage data",
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'Ax'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                't/integration/coverage/a.tx' => {env => {COVER_TEST_SUBTESTS => 'a, b, c'}, stdin => "a\nb\nc\n", argv => ['a', 'b', 'c']},
                't/integration/coverage/c.tx' => {env => {COVER_TEST_SUBTESTS => 'a, c'},    stdin => "a\nc\n",    argv => ['a', 'c']},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'Bx'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                # No manager, so run entire tests
                't/integration/coverage/b.tx'    => {argv => [], env => {}, stdin => ''},
                't/integration/coverage/x.tx'    => {argv => [], env => {}, stdin => ''},
                't/integration/coverage/open.tx' => {argv => [], env => {}, stdin => ''},

                # Managed, so we have custom input
                't/integration/coverage/a.tx' => {'argv' => ['b', 'c'], 'env' => {'COVER_TEST_SUBTESTS' => 'b, c'}, 'stdin' => "b\nc\n"},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'Cx'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                "t/integration/coverage/a.tx" => {"argv" => ["c"], "env" => {"COVER_TEST_SUBTESTS" => "c"}, "stdin" => "c\n"},
                "t/integration/coverage/c.tx" => {"argv" => ["c"], "env" => {"COVER_TEST_SUBTESTS" => "c"}, "stdin" => "c\n"},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'Bxb'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                "t/integration/coverage/b.tx"    => {"argv" => [], "env" => {}, "stdin" => ""},
                "t/integration/coverage/open.tx" => {"argv" => [], "env" => {}, "stdin" => ""},
                "t/integration/coverage/x.tx"    => {"argv" => [], "env" => {}, "stdin" => ""},

                "t/integration/coverage/a.tx" => {"argv" => ["b", "c"], "env" => {"COVER_TEST_SUBTESTS" => "b, c"}, "stdin" => "b\nc\n"},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'Cxc'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                "t/integration/coverage/a.tx" => {"argv" => ["c"], "env" => {"COVER_TEST_SUBTESTS" => "c"}, "stdin" => "c\n"},
                "t/integration/coverage/c.tx" => {"argv" => ["c"], "env" => {"COVER_TEST_SUBTESTS" => "c"}, "stdin" => "c\n"},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'Ax*'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                "t/integration/coverage/a.tx" => {"argv" => ["a", "b", "c"], "env" => {"COVER_TEST_SUBTESTS" => "a, b, c"}, "stdin" => "a\nb\nc\n"},
                "t/integration/coverage/c.tx" => {"argv" => ["a", "c"],      "env" => {"COVER_TEST_SUBTESTS" => "a, c"},    "stdin" => "a\nc\n"},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'Axa'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                "t/integration/coverage/a.tx" => {"argv" => ["a", "b", "c"], "env" => {"COVER_TEST_SUBTESTS" => "a, b, c"}, "stdin" => "a\nb\nc\n"},
                "t/integration/coverage/c.tx" => {"argv" => ["a", "c"],      "env" => {"COVER_TEST_SUBTESTS" => "a, c"},    "stdin" => "a\nc\n"},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'Axaa'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                "t/integration/coverage/a.tx" => {"argv" => ["a"], "env" => {"COVER_TEST_SUBTESTS" => "a"}, "stdin" => "a\n"},
                "t/integration/coverage/c.tx" => {"argv" => ["a"], "env" => {"COVER_TEST_SUBTESTS" => "a"}, "stdin" => "a\n"},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'Axaaa'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                "t/integration/coverage/a.tx" => {"argv" => ["a", "b", "c"], "env" => {"COVER_TEST_SUBTESTS" => "a, b, c"}, "stdin" => "a\nb\nc\n"},
                "t/integration/coverage/c.tx" => {"argv" => ["a", "c"],      "env" => {"COVER_TEST_SUBTESTS" => "a, c"},    "stdin" => "a\nc\n"},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

yath(
    command => 'test',
    args    => ["-D$dir/lib", "-I$dir/lib", '--ext=tx', "--cover-from=$cfile", '--plugin' => '+Plugin', '--changed-only', '-v'],
    exit    => 0,
    env     => {TEST_CASE => 'AxCx'},
    test    => sub {
        my $out   = shift;
        my $input = +{$out->{output} =~ m/INPUT (\S+): (\{.+\})$/gm};
        $_ = decode_json($_) for values %$input;
        is(
            $input,
            {
                "t/integration/coverage/a.tx" => {"argv" => ["a", "b", "c"], "env" => {"COVER_TEST_SUBTESTS" => "a, b, c"}, "stdin" => "a\nb\nc\n"},
                "t/integration/coverage/c.tx" => {"argv" => ["a", "c"],      "env" => {"COVER_TEST_SUBTESTS" => "a, c"},    "stdin" => "a\nc\n"},
            },
            "Test got the correct input about what subtests to run",
        );
    },
);

done_testing;
