The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/env perl

use strict;
use warnings;
use Test::More;
use Test::Exception;
use Role::Tiny;
use Catmandu::ArrayIterator;

my $pkg;

BEGIN {
    $pkg = 'Catmandu::Validator';
    use_ok $pkg;
}
require_ok $pkg;

{

    package T::ValidatorWithoutValidateHash;
    use Moo;

    package T::Validator;
    use Moo;
    with $pkg;

    sub validate_data {
        $_[1]->{field} =~ /^1|7$/ ? undef : ["Value is not 1"];
    }

}

throws_ok {
    Role::Tiny->apply_role_to_package('T::ValidatorWithoutValidateOne', $pkg)
}
qr/missing validate_data/;

my $e = T::Validator->new;

can_ok $e, 'is_valid';
can_ok $e, 'validate';

# throw:: TODO make sure it is a hash for single one.
throws_ok {$e->validate(1)} qr/Cannot validate data of this type/;

#
my $href0 = {field => 0};
my $href1 = {field => 1};

is $e->validate($href1), $href1, 'validate() - success';
is $e->validate($href0), undef, 'validate() - fails';

is_deeply($e->last_errors, ['Value is not 1'], 'last_errors returns errors');

is $e->is_valid($href1), 1, 'is_valid returns 1';
is $e->is_valid($href0), 0, 'is_valid returns 0';

my $after_callback_called = 0;
$e = T::Validator->new(
    after_callback => sub {$after_callback_called = 1, $_[0]});
is $e->validate($href1), $href1, 'validate, after_callback - success';
is $after_callback_called, 1, 'validate, after_callback - called';

my $arr
    = $e->validate([{field => 2}, {field => 1}, {field => 0}, {field => 3}]);

is $e->valid_count,   1, 'valid_count';
is $e->invalid_count, 3, 'invalid_count';

my $error_field              = '_validation_errors';
my $validation_error_message = "Value is not 1";
my $e_efield                 = T::Validator->new(error_field => 1);
is_deeply $e_efield->validate([{field => 5}, {field => 3}, {field => 1}]),
    [
    {field => 5, $error_field => [$validation_error_message]},
    {field => 3, $error_field => [$validation_error_message]},
    {field => 1}
    ],
    'validate, error_field 1';

my $error_field_new = 'my_error';

$e_efield = T::Validator->new(error_field => $error_field_new);

is_deeply $e_efield->validate([{field => 6}, {field => 3}, {field => 1}]),
    [
    {field => 6, $error_field_new => [$validation_error_message]},
    {field => 3, $error_field_new => [$validation_error_message]},
    {field => 1}
    ],
    'validate, error_field 2';

my @invalid_array;

my $validator = T::Validator->new(
    after_callback => sub {
        my ($hashref, $errors) = @_;
        if ($errors) {
            $hashref->{errors} = $errors;
            push @invalid_array, $hashref;
            return;
        }
        else {
            $hashref->{valid} = 1;
        }
        $hashref;
    }
);

my $passed_array
    = $validator->validate([{field => 3}, {field => 1}, {field => 2}]);

is_deeply $passed_array, [{field => 1, valid => 1}],
    'validate, after_callback - valid';
is_deeply \@invalid_array,
    [
    {field => 3, errors => [$validation_error_message]},
    {field => 2, errors => [$validation_error_message]},
    ],
    'validate, after_callback - invalid';

my $x = 0;
@invalid_array = ();
$validator
    = T::Validator->new(error_callback => sub {push @invalid_array, $_[0]});
$passed_array
    = $validator->validate([{field => 1}, {field => 8}, {field => 9}]);
is_deeply $passed_array, [{field => 1}],
    'validate (array) - valid records returned';
is_deeply \@invalid_array, [{field => 8}, {field => 9}],
    'validate - invalid records returned';

# test iterator

my $it = Catmandu::ArrayIterator->new(
    [{field => 1}, {field => 8}, {field => 7}]);
$validator = T::Validator->new;
my $new_it = $validator->validate($it);
is_deeply $new_it->to_array, [{field => 1}, {field => 7}],
    'validate (iterator) - iterator returned';

done_testing 22;