use Test::WWW::Mechanize::CGIApp;
use WWW::Mechanize::TreeBuilder;
use HTML::TreeBuilder::XPath; # findnodes()
use Test::Builder::Tester;

use Data::Dumper;
use Data::Printer alias => 'ddp';

use strict;
use warnings;

use Test::More tests => 96;
# use Test::More 'no_plan';

=begin: tests:
0) create some request_lab_test_status entries
1) test display/print worklist
2) test data entry
3) check history
4) different section with outstanding tests, sign-out 1 test & change user
5) delete one record
6) unscreened requests
7) unreported requests
8) urgent requests
=cut

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

my $mech = get_mech();
WWW::Mechanize::TreeBuilder->meta->apply($mech);

do_login();

my $dbh;

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

my $dbix = get_dbix();

# create some request_lab_test_status entries:
{
    for my $request_id ( 1, 2 ) {
        for my $lab_test_id (1 .. 5) {
            my %args = (
                request_id  => $request_id,
                lab_test_id => $lab_test_id,
                user_id => 1,
                status_option_id => 1,
            );
            $dbix->insert( 'request_lab_test_status', \%args );
        }
    }

    # make 2 requests urgent & doi:
    for ( 1, 2 ) {
        $dbix->insert( 'request_option', { request_id => $_, option_id => $_ } );
    }

    # request_lab_section_notes:
    $dbix->insert(
        'request_lab_section_notes',
        { request_id => 1, lab_section_id => 1, details => 'test detail' }
    );

    # create new user:
    my %user = (
        username => 'user',
        last_name => 'user_lname',
        first_name => 'user_fname',
        password => 'pwd',
        user_location_id => 1,
        designation => 'user',
        group_id => 3,
        active => 'yes',
    );
    $dbix->insert( 'users', \%user );
}

$mech->get_ok('/worklist');                                   # print_and_exit();
# test display:
{
    $mech->field( lab_section_id => 1 );
    $mech->submit();                                          # print_and_exit();

    $mech->form_name('display');
    $mech->click_button(value => 'Display');                  # print_and_exit();                                          # print_and_exit();

    foreach( qw/AML CML HIV PNH/ ) {
        $mech->has_tag_like(
            td => qr($_),
            'OK: expected lab test detected',
        );
    }                                                          # print_and_exit();
    # expect 8 tests total:
    foreach( 1 .. 8 ) {
        $mech->has_tag(
            td => $_,
            "OK: outstanding test $_ detected",
        );
    }                                                         # print_and_exit();
    # urgent requests:
    $mech->content_like(
        qr(<td class="red">\s+GREEN,\s+Alan\s+</td>),
        "OK: expected request option detected",
    );
    # urgent requests:
    $mech->content_like(
        qr(<td>\s+\[P\] AML\s+</td>),
        "OK: expected request option detected",
    );
    # lab_test_details:
    $mech->has_tag(
        td => 'test detail',
        "OK: expected lab_test detail detected",
    );
}                                                            # print_and_exit();

# test data entry:
{
    $mech->back();                                            # print_and_exit();

    $mech->form_name('display');
    $mech->click_button(value => 'Data Entry');               # print_and_exit();

    $mech->form_name('update_results');

    # omit status_option_id (can't omit user_id - no blank opt):
    $mech->submit();                                          # print_and_exit();

    has_dfv_errors();
    has_missing();                                              # print_and_exit();

    # set status to 'complete':
    $mech->field(status_option_id => 2);
    $mech->submit();                                          # print_and_exit();

    # should have 'no lab test data' warning:
    $mech->has_tag_like(
        p => get_messages('worklist')->{no_lab_test_ids},
        'OK: data warning detected',
    );                                                        # print_and_exit();

    # select flow section: already on data entry page!!
#    $mech->form_name('display');
#    $mech->click_button(value => 'Data Entry');                print_and_exit();

    # sign off AML's & CML's:
    foreach (2,3,7,8) {
        $mech->tick('request_lab_test_id', $_);
    }
    # set status to complete:
    $mech->field(status_option_id => 2);
    $mech->submit();                                           # print_and_exit();

    $mech->has_tag(
        p => 'INFO: records updated successfully',
        'OK: expected success message received',
    );
    $mech->has_tag(
        td => 'complete', # all rows will be same
        'OK: expected status detected',
    );

    # check correct username diaplayed:
    $mech->has_tag(
        td => 'ADMIN',
        'OK: expected username displayed',
    );                                                        # print_and_exit();

    # just check AML's & CML cleared from worklist display:
    $mech->get_ok('/worklist/select?lab_section_id=1');       # print_and_exit();

    $mech->form_name('display');
    $mech->submit();                                          # print_and_exit();

    # has PNH & HIV, lacks AML & CML:
    foreach ( qw/PNH HIV/ ) {
        $mech->has_tag(
            td => "[P] $_",
            'OK: expected outstanding test detected',
        );
    }
    foreach ( qw/AML CML/ ) {
        test_out( 'not ok 1 - foo' );
        test_fail( +1 );
        $mech->has_tag( td => "[P] $_", 'foo' );
        test_test( 'OK: outstanding test not detected' );     # print_and_exit();
    }
}

# check history:
foreach my $request_id (1, 2) {
    $mech->get_ok('/history/=/'.$request_id);                # print_and_exit();

    foreach( qw/AML CML/ ) {
        $mech->has_tag(
            td => "set $_ status to complete",
            'OK: expected history log for test found',
        );
    }
    foreach( qw/PNH HIV/ ) {
        test_out( 'not ok 1 - foo' );
        test_fail( +1 );
        $mech->has_tag( td => "set $_ status to complete", 'foo' );
        test_test( 'OK: history log for test not found' );    # print_and_exit();
    }
}

# different section with outstanding tests, sign-off 1 test & change user:
$mech->get_ok('/worklist/select?lab_section_id=3');          #  print_and_exit();
{
    $mech->form_name('display');
    $mech->submit();                                          # print_and_exit();

    $mech->has_tag(
        td => '[P] APML',
        'OK: expected lab test detected',
    );

    # expect 2 tests total:
    foreach(1,2) {
        $mech->has_tag(
            td => $_,
            "OK: outstanding test $_ detected",
        );
    }
    $mech->back();                                            # print_and_exit();

    # select data entry form:
    $mech->form_name('display');
    $mech->click_button(value => 'Data Entry');               # print_and_exit();

    $mech->form_name('update_results');

    # change user:
    $mech->field( user_id => 2 );
    $mech->field( status_option_id => 4 ); # setup
    # sign off 1 test:
    $mech->tick('request_lab_test_id', 5);

    $mech->submit();                                          # print_and_exit();

    $mech->has_tag(
        p => 'INFO: records updated successfully',
        'OK: expected success message received',
    );

    # check status
    $mech->has_tag(
        td => 'setup', # all rows will be same
        'OK: expected status detected',
    );

    # check correct username diaplayed:
    $mech->has_tag(
        td => 'USER',
        'OK: expected username displayed',
    );                                                        # print_and_exit();

    # check history:
    $mech->get_ok('/history/=/1');                            # print_and_exit();
    $mech->has_tag(
        td => 'set APML status to setup for USER',
        'OK: expected history data found'
    );

    # check display for this section:
    $mech->get_ok('/worklist/select?lab_section_id=3');       # print_and_exit();

    $mech->form_name('display');
    $mech->submit();                                          # print_and_exit();

    # should still be 2 oustanding:
    foreach (1,2) {
        $mech->has_tag(
            td => $_,
            'OK: outstanding test number displayed',
        );
    }

    # one 'new' & one 'setup':
    foreach (qw/new setup/) {
        $mech->has_tag(
            td => uc $_,
            'OK: expected test status displayed',
        );
    }                                                         # print_and_exit();
}

# check history for both requests:
{
    $mech->get_ok('/history/=/1');                            # print_and_exit();
    $mech->has_tag_like(
        td => qr(set APML status to setup), # + 'for user foo'
        'OK: expected history log for test found',
    );

    $mech->get_ok('/history/=/2');                            # print_and_exit();
    test_out( 'not ok 1 - foo' );
    test_fail( +1 );
    $mech->has_tag_like( td => qr(set APML status to setup), 'foo' );
    test_test( 'OK: history log for test not found' );
}

# section with no outstanding tests (can't be done now only active sections loaded):
=begin
$mech->get_ok('/worklist/select?lab_section_id=2');            print_and_exit();
{
    $mech->form_name('display');
    $mech->submit();                                           print_and_exit();

    my $msg = sprintf get_messages('worklist')->{no_outstanding_tests_for_section},
        'Histology';
    $mech->has_tag_like(
        p => $msg,
        'OK: no outstanding tests for selected section',
    );
}
=cut

# delete one:
{
    $mech->get_ok('/worklist/select?lab_section_id=3');       # print_and_exit();

    $mech->form_name('display');
    $mech->click_button(value => 'Data Entry');               # print_and_exit();

    $mech->form_name('update_results');

    $mech->field( user_id => 1 );
    $mech->field( status_option_id => 3 ); # delete
    # check one test:
    $mech->tick('request_lab_test_id', 10); # APML

    $mech->submit();                                          # print_and_exit();

    # have failed to click 'confirm delete' box:
    has_dfv_errors();
    has_missing;                                              # print_and_exit();

    $mech->field( status_option_id => 3 ); # delete
    $mech->tick( 'confirm_delete', 1 ); # confirm

    $mech->submit();                                          # print_and_exit();

    $mech->has_tag(
        p => 'INFO: records updated successfully',
        'OK: expected success message received',
    );

    # check status
    $mech->has_tag(
        td => 'delete',
        'OK: expected status detected',
    );                                                         # print_and_exit();

    # check display for this section:
    $mech->get_ok('/worklist/select?lab_section_id=3');       # print_and_exit();

    $mech->form_name('display');
    $mech->submit();                                          # print_and_exit();

    # should only be 1 oustanding:
    $mech->has_tag(
        td => 1,
        'OK: outstanding test number displayed',
    );
    test_out( 'not ok 1 - foo' );
    test_fail( +1 );
    $mech->has_tag( td => 2, 'foo' );
    test_test( 'OK: outstanding test number not detected' );

    # only 'setup' should be left:
    $mech->has_tag(
        td => 'SETUP',
        'OK: expected test status displayed',
    );
    test_out( 'not ok 1 - foo' );
    test_fail( +1 );
    $mech->has_tag( td => 'NEW', 'foo' );
    test_test( 'OK: outstanding test status not detected' );  # print_and_exit();

    $mech->get_ok('/history/=/2');                            # print_and_exit();
    $mech->has_tag(
        td => 'deleted APML entry',
        'OK: expected history log for test found',
    );
}

# unscreened requests:
$mech->get_ok('/worklist');                                   # print_and_exit();
{
    $mech->form_name('status');
    $mech->field( status_query => 'unscreened' );
    $mech->submit();                                          # print_and_exit();

    $mech->text_contains(
       'Request status - unscreened cases [2]',
        'OK: expected title detected',
    );

    foreach (1,2) {
        $mech->has_tag(
            td => $_,
            'OK: expected request number detected',
        );
    }
    { # selects all the span elements that have a "class" attribute with a value of "green"
        my @nodes = $mech->tree->findnodes( q!//span[@class='green']! ); # ddp @nodes;
        is( @nodes, 2, 'OK: expected span class detected' );
        my $expr = '\[0\]'; # naf method but works!
        my $c = () = $mech->text =~ /$expr/g;
        is( $c, 2, 'OK: expected delta values detected' );
    }                                                        # print_and_exit();
}

# unreported requests (none coz none screened yet):
$mech->get_ok('/worklist');                                   # print_and_exit();
{
    $mech->form_name('status');
    $mech->field( status_query => 'unreported' );
    $mech->submit();                                          # print_and_exit();

    test_out( 'not ok 1 - foo' );
    test_fail( +1 );
    $mech->has_tag( h3 => 'Request status - unreported cases', 'foo' );
    test_test( 'OK: title not found' );

    my $msg = get_messages('worklist')->{no_outstanding_requests}; # warn $msg;
    $mech->has_tag_like(
        p => qr($msg),
        'OK: no outstanding requests message detected',
    );                                                        # print_and_exit();
}

# urgent requests:
$mech->get_ok('/worklist');                                   # print_and_exit();
{
    $mech->form_name('status');
    $mech->field( status_query => 'urgent' );
    $mech->submit();                                          # print_and_exit();

    $mech->text_contains(
        'Request status - urgent cases [1]',
        'OK: expected title detected',
    );

    # only expect 1 case:
    $mech->has_tag(
        td => 1,
        'OK: expected request detected',
    );
    test_out( 'not ok 1 - foo' );
    test_fail( +1 );
    $mech->has_tag( td => 2, 'foo' );
    test_test( 'OK: additional requests not found' );

    { # selects all the span elements that have a "class" attribute with a value of "green"
        my @nodes = $mech->tree->findnodes( q!//span[@class='green']! ); # ddp @nodes;
        is( @nodes, 1, 'OK: expected span class detected' );
        my $expr = '\[0\]'; # naf method but works!
        my $c = () = $mech->text =~ /$expr/g;
        is( $c, 1, 'OK: expected delta value detected' );
    }                                                         # print_and_exit();
}

# $dbix->delete('request_specimen_detail'); # uncomment to test insert works on new record
{
# gross description worklist (test both update & insert functions):
    $mech->get('/local_worklist?function_name=gross_description'); # print_and_exit;
    $mech->form_name('gross_description_1');
    $mech->field( gross_description => 'biopsy' );
    $mech->submit();                                            # print_and_exit;

    $mech->content_contains(
        get_messages('action')->{edit_success},
        'OK: new record succeeded',
    );                                                          # print_and_exit();
    $mech->form_name('gross_description_1');
    is( $mech->value('gross_description'),
       'biopsy', 'OK: expected value on insert'
    );
}
{ # update value:
    $mech->get('/local_worklist?function_name=gross_description'); # print_and_exit;
    $mech->form_name('gross_description_1');
    $mech->field( gross_description => 'aspirate' );
    $mech->submit();                                            # print_and_exit;

    $mech->content_contains(
        get_messages('action')->{edit_success},
        'OK: new record succeeded',
    );                                                          # print_and_exit();
    $mech->form_name('gross_description_1');
    is( $mech->value('gross_description'),
        'aspirate', 'OK: expected value on update');
}
{ # delete existing value:
    $mech->get('/local_worklist?function_name=gross_description'); # print_and_exit;
    $mech->form_name('gross_description_1');
    $mech->field( gross_description => undef );
    $mech->submit();                                            # print_and_exit;

    $mech->content_contains(
        get_messages('action')->{edit_success},
        'OK: new record succeeded',
    );                                                          # print_and_exit();
    $mech->form_name('gross_description_1');
    is( $mech->value('gross_description'),
        '', 'OK: expected value on update');
}
{ # submit empty value (only tests no error on empty field submit):
    $mech->get('/local_worklist?function_name=gross_description'); # print_and_exit;
    $mech->form_name('gross_description_2');
    $mech->field( gross_description => undef );
    $mech->submit();                                            # print_and_exit;

    $mech->content_contains(
        get_messages('action')->{edit_success},
        'OK: new record succeeded',
    );                                                          # print_and_exit();
    $mech->form_name('gross_description_2');
    is( $mech->value('gross_description'),
        '', 'OK: expected value on insert');
}

do_logout();
