#!/usr/bin/perl

use Test::WWW::Mechanize::CGIApp;
use Test::Builder::Tester;

use Data::Dumper;

use strict;
use warnings;

use Test::More; #  use Test::More 'no_plan';
use constant TESTS => 40;

=begin: tests:
tests results data entry using date, datetime, integer & decimal data types
also tests specific formats from result_data_validation.yml
=cut

BEGIN {
    require 't/test-lib.pl';
}

ok( get_yaml('results_data_validation') , "require a results_data_validation.yml file" ); # check for required yaml file

my $mech = get_mech();

do_login();

my $dbh;

eval {
    $dbh = get_dbh() or die 'no database handle recieved from get_dbh';
};

warn $@ if $@;

my $dbix = get_dbix();

# register new data-types
$dbix->insert('lab_test_result_data_types', { description => $_ })
    for qw(integer decimal date datetime);
my $data_type_map = $dbix->select('lab_test_result_data_types',
    [ qw(description id) ])->map;

# register new lab tests with data-types & validators:
{ # CD1 = integer
    $dbix->insert('lab_tests', { test_name => 'cd1', field_label => 'CD1',
        lab_section_id => 1, test_type => 'test', has_results => 'yes' });
    my $tid = get_last_insert_id('lab_tests');
    $dbix->insert('lab_test_data_type',
        { lab_test_id => $tid, data_type_id => $data_type_map->{integer} });
}
{ # CD2 = decimal
    $dbix->insert('lab_tests', { test_name => 'cd2', field_label => 'CD2',
        lab_section_id => 1, test_type => 'test', has_results => 'yes' });
    my $tid = get_last_insert_id('lab_tests');
    $dbix->insert('lab_test_data_type',
        { lab_test_id => $tid, data_type_id => $data_type_map->{decimal} });
}
{ # CD3 = integer
    $dbix->insert('lab_tests', { test_name => 'cd3', field_label => 'CD3',
        lab_section_id => 1, test_type => 'test', has_results => 'yes' });
    my $tid = get_last_insert_id('lab_tests');
    $dbix->insert('lab_test_data_type',
        { lab_test_id => $tid, data_type_id => $data_type_map->{integer} });
}
{ # date = date
    $dbix->insert('lab_tests', { test_name => 'date', field_label => 'Date',
        lab_section_id => 1, test_type => 'test', has_results => 'yes' });
    my $tid = get_last_insert_id('lab_tests');
    $dbix->insert('lab_test_data_type',
        { lab_test_id => $tid, data_type_id => $data_type_map->{date} });
}
{ # datetime = datetime
    $dbix->insert('lab_tests', { test_name => 'datetime', field_label => 'DateTime',
        lab_section_id => 1, test_type => 'test', has_results => 'yes' });
    my $tid = get_last_insert_id('lab_tests');
    $dbix->insert('lab_test_data_type',
        { lab_test_id => $tid, data_type_id => $data_type_map->{datetime} });
}
{ # yaml-file defined valdaition (use name unlikely ever to be used in app):
    $dbix->insert('lab_tests', {
        test_name => '__xx_test_result_1', field_label => 'T1',
        lab_section_id => 1, test_type => 'test', has_results => 'yes' });
    my $tid = get_last_insert_id('lab_tests');
    $dbix->insert('lab_test_data_type',
        { lab_test_id => $tid, data_type_id => $data_type_map->{decimal} });
}
{ # yaml-file defined valdaition (use name unlikely ever to be used in app):
    $dbix->insert('lab_tests', {
        test_name => '__xx_test_result_2', field_label => 'T2',
        lab_section_id => 1, test_type => 'test', has_results => 'yes' });
    my $tid = get_last_insert_id('lab_tests');
    $dbix->insert('lab_test_data_type',
        { lab_test_id => $tid, data_type_id =>$data_type_map->{integer} });
}
{ # volume = integer (tests zero result)
    $dbix->insert('lab_tests', { test_name => 'vol', field_label => 'Volume',
        lab_section_id => 1, test_type => 'test', has_results => 'yes' });
    my $tid = get_last_insert_id('lab_tests');
    $dbix->insert('lab_test_data_type',
        { lab_test_id => $tid, data_type_id => $data_type_map->{integer} });
}
#===============================================================================
{ # request lab-tests:
    $mech->get_ok('/result/=/2');
    $mech->form_name('flow_requests');
    $mech->tick('test_id', $_, 1) for (10 .. 16);
    $mech->submit();                                          # print_and_exit();
}
{ # invalid integer:
    my $test_id = 'lab_test_id_10'; # cd1
    my $result  = 2;

    $mech->get_ok('/result/=/2');
    $mech->form_name('flow_results');
    # enter invalid result:
    $mech->field($test_id, '1.2');
    $mech->submit();                                          # print_and_exit();
    my $err_msg = get_messages('dfv_msgs')->{need_integer}; # warn $err_msg;
    $mech->text_contains(
        $err_msg,
        "OK: failed validation [$err_msg]",
    );                                                        # print_and_exit();
    # correct format:
    $mech->form_name('flow_results');
    $mech->field($test_id, $result);
    $mech->submit();                                         # print_and_exit();
    $mech->has_tag(
        p => 'INFO: results data update successful',
        'OK: results update success',
    );
    check_result($test_id, $result);
}
{ # invalid decimal:
    my $test_id = 'lab_test_id_11'; # cd2
    my $result  = 1.2;
    $mech->get_ok('/result/=/2');
    $mech->form_name('flow_results');
    # enter invalid result:
    $mech->field($test_id, 2);
    $mech->submit();                                          # print_and_exit();
    my $err_msg = get_messages('dfv_msgs')->{need_decimal};
    $mech->text_contains(
        $err_msg,
        "OK: failed validation [$err_msg]",
    );
    # correct format:
    $mech->form_name('flow_results');
    $mech->field($test_id, $result);
    $mech->submit();                                          # print_and_exit();
    $mech->has_tag(
        p => 'INFO: results data update successful',
        'OK: results update success',
    );
    check_result($test_id, $result);
}
{ # invalid date:
    my $test_id = 'lab_test_id_13'; # date
    my $result  = '2015-08-12';
    $mech->get_ok('/result/=/2');
    $mech->form_name('flow_results');
    # enter invalid result:
    $mech->field($test_id, '2015-18-12');
    $mech->submit();                                          # print_and_exit();
    my $err_msg = get_messages('dfv_msgs')->{invalid_date};
    $mech->text_contains(
        $err_msg,
        "OK: failed validation [$err_msg]",
    );
    # correct format:
    $mech->form_name('flow_results');
    $mech->field($test_id, $result);
    $mech->submit();                                          # print_and_exit();
    $mech->has_tag(
        p => 'INFO: results data update successful',
        'OK: results update success',
    );
    check_result($test_id, $result);
}
{ # invalid datetime:
    my $test_id = 'lab_test_id_14'; # datetime
    my $result  = '2015-08-12 12:18:22';

    $mech->get_ok('/result/=/2');
    $mech->form_name('flow_results');
    # enter invalid result:
    $mech->field($test_id, '2015-18-12 12:18:22');
    $mech->submit();                                          # print_and_exit();
    my $err_msg = get_messages('dfv_msgs')->{invalid_datetime};
    $mech->text_contains(
        $err_msg,
        "OK: failed validation [$err_msg]",
    );
    # correct format:
    $mech->form_name('flow_results');
    $mech->field($test_id, $result);
    $mech->submit();                                          # print_and_exit();
    $mech->has_tag(
        p => 'INFO: results data update successful',
        'OK: results update success',
    );
    check_result($test_id, $result);
}
{ # invalid format using yaml file:
    my $test_id = 'lab_test_id_15'; # __xx_test_result_1
    my $result  = 1234567.2;

    $mech->get_ok('/result/=/2');
    $mech->form_name('flow_results');
    # enter invalid result:
    $mech->field($test_id, 2);
    $mech->submit();                                          # print_and_exit();
    my $err_msg = get_messages('dfv_msgs')->{need_decimal};
    $mech->text_contains(
        $err_msg,
        "OK: failed validation [$err_msg]",
    );
    # decimal but still invalid format:
    $mech->form_name('flow_results');
    $mech->field($test_id, '123456.2');
    $mech->submit();                                          # print_and_exit();
    $err_msg = get_messages('dfv_msgs')->{invalid_format};
    $mech->text_contains(
        $err_msg,
        "OK: failed validation [$err_msg]",
    );
    # correct format:
    $mech->form_name('flow_results');
    $mech->field($test_id, $result);
    $mech->submit();                                          # print_and_exit();
    $mech->has_tag(
        p => 'INFO: results data update successful',
        'OK: results update success',
    );
    check_result($test_id, $result);
}
{ # invalid format using yaml file:
    my $test_id = 'lab_test_id_16'; # __xx_test_result_2
    my $result  = 12345678;

    $mech->get_ok('/result/=/2');
    $mech->form_name('flow_results');
    # enter invalid result:
    $mech->field($test_id, 2.2);
    $mech->submit();                                          # print_and_exit();
    my $err_msg = get_messages('dfv_msgs')->{need_integer};
    $mech->text_contains(
        $err_msg,
        "OK: failed validation [$err_msg]",
    );
    # integer but still invalid format:
    $mech->form_name('flow_results');
    $mech->field($test_id, '1234567');
    $mech->submit();                                          # print_and_exit();
    $err_msg = get_messages('dfv_msgs')->{invalid_format};
    $mech->text_contains(
        $err_msg,
        "OK: failed validation [$err_msg]",
    );
    # correct format:
    $mech->form_name('flow_results');
    $mech->field($test_id, $result);
    $mech->submit();                                          # print_and_exit();
    $mech->has_tag(
        p => 'INFO: results data update successful',
        'OK: results update success',
    );
    check_result($test_id, $result);
}
{ # change existing result to invalid format, resubmit form with new valid param:
    $dbix->update('request_lab_test_results', { result => '1234567_2' },
        { result => '1234567.2' }); # lab_test_id_14

    my $test_id = 'lab_test_id_12';
    my $result  = 22;
    $mech->get_ok('/result/=/2');
    $mech->form_name('flow_results');
    # enter valid integer result:
    $mech->field($test_id, $result);
    $mech->submit();                                          # print_and_exit();
    check_result($test_id, $result);

    # still get validation failure from lab_test_id_14:
    my $err_msg = get_messages('dfv_msgs')->{need_decimal};
    $mech->text_contains(
        $err_msg,
        "OK: failed validation [$err_msg]",
    );
    # change back to valid result or any subsequent form submissions will fail:
    $dbix->update('request_lab_test_results', { result => '1234567.2' },
        { result => '1234567_2' }); # lab_test_id_14
}
{ # check 'zero' result:
    my $test_id = 'lab_test_id_17'; # volume
    my $result  = 0; # valid but false value - check RfC405L patch works:

    $mech->get_ok('/result/=/2');
    $mech->form_name('flow_results');
    $mech->field($test_id, $result);
    $mech->submit();                                         # print_and_exit();
    $mech->has_tag(
        p => 'INFO: results data update successful',
        'OK: results update success',
    );
    check_result($test_id, $result);
}

do_logout();
done_testing(TESTS);

sub check_result {
    my ($test_id, $result) = @_;
    $mech->form_name('flow_results');
    is( $mech->value($test_id), $result, 'OK: expected test result'); # print_and_exit();
}
