#!/usr/bin/env perl
use 5.22.0;

use FindBin;
use lib $FindBin::Bin.'/lib';

use strict;
use autodie;
use warnings;
use Data::Dumper;
use Getopt::Long;
use List::Util qw/uniq/;
use Storable;

use Module;
use CpanFile;
use TestCpanInc;

my $opt_cpanfile;
my $opt_module;
my $opt_help;
my $opt_jobstor='';
my $opt_pass=1;

GetOptions ("module=s" => \$opt_module,
            "cpanfile=s"   => \$opt_cpanfile,      # string
            "perlbrew_env=s" => \$TestCpanInc::perlbrew_env,
            "jobstor=s" => \$opt_jobstor,
            "pass=n" => \$opt_pass,
            "help"  => \$opt_help);   # flagV

if ((!$opt_module && !$opt_cpanfile) || ($opt_module && $opt_cpanfile) || $opt_help) {
    print "Call with either --cpanfile xor --module to specify what to test.\n",
          "Use --perlbrew_env to specify which perl install to use, defaults to blead\n",
          "Add --jobstor to save progress for resuming, and examining later\n",
          "Use --pass to do another pass on the modules, defaults to 1, only reruns failures\n";
    exit(1);
}

$|++;
close(STDIN);

my @modules;
my %jobstatus;
if (!-e $opt_jobstor) {
    my @mods_to_test = ($opt_module);

    if ($opt_cpanfile) {
    # TODO read cpanfile, via do/require
        cpanfile::__parse_file($opt_cpanfile);
        @mods_to_test = @cpanfile::mods;
    }

    print "Building dep list sorry, this'll take a while\n";
    for my $mtt (@mods_to_test) {
        my $mod = Module->new_module($mtt);
        push @modules, map {$_->name} uniq TestCpanInc::dep_order($mod);
    }
    print "\n";
    @modules = uniq(@modules);
} else {
    my $data = retrieve($opt_jobstor);
    @modules = $data->{modules}->@*;
    %jobstatus = $data->{jobstatus}->%*;
}

sub __save_cache {
    if ($opt_jobstor) {
        store {modules => \@modules, jobstatus => \%jobstatus}, $opt_jobstor;
    }
};
END {__save_cache};

for my $mod (@modules) {
    print "Testing $mod\n";
    my $status = $jobstatus{$mod}{status} // "";
    my $tested = $jobstatus{$mod}{tested} // 0;
    if ($tested != $opt_pass && $status ne "success" && $status ne 'manual failure' ) {
        print "STATUS => $status, PASS => $opt_pass, TESTED => $tested\n" if $opt_pass != 1;
        my $status = TestCpanInc::test_module($mod);
        $jobstatus{$mod}{tested} = $opt_pass;
        $jobstatus{$mod}{status} = $status;
        __save_cache;
    }
}
