#!/usr/bin/perl

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

use Data::Dumper;

use strict;
use warnings;

use constant TESTS => 89;

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

# tests rules for requiring diagnosis confirmation at report stage:

=begin: tests:
all tests performed on a request with a molecular results summary:

1) screen = PNH; exempt
2) screen = CML interferon follow-up; specimen = LU
3) screen = CML interferon follow-up; specimen = PB; exempt
4) screen = CMPD pres & follow-up; specimen = PB; additional tests 
5) screen = CMPD pres & follow-up; specimen = PB + BMAT 
6) screen = CMPD pres & follow-up; specimen = PB; exempt
7) screen = CMPD pres & follow-up; specimen = PB; delayed result summary
=cut

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

my $dbh;

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

warn $@ if $@;

# vars needed if tests are run:
use vars qw($mech $dbix $spell_check_required);

my $yaml = get_yaml('diagnosis_confirm'); # warn Dumper $yaml;

if ($yaml) {
    $mech = get_mech();
    $dbix = get_dbix();

    # need to see if 'require_spell_check' is required:
    $spell_check_required = is_spell_check_required(); # warn $spell_check_required;
}

SKIP: {
    skip('these tests require config/.local/settings/diagnosis_confirm.yml file',TESTS)
        unless $yaml;
    do_all_tests();
}

sub do_all_tests {

    do_login();

# register some new data (fresh tissue):
{   # new screen term which requires a final_diagnosis check:    
    $dbix->insert('screens',
        { description => 'CML interferon follow-up', category_id => 1 }
    );
    # new screen term which doesn't require a final_diagnosis check (if PB & jak2):    
    $dbix->insert('screens',
        { description => 'CMPD pres & follow-up', category_id => 1 }
    );
    $dbix->insert( 'lab_tests',
        { test_name => 'jak2', field_label => 'JAK2', lab_section_id => 3,
            test_type => 'test', has_results => 'no' }
    );
    { # lab_test_sample_type:
        my $lab_test_id = get_last_insert_id('lab_tests'); 
       	my $sample_type_ids = $dbix->select('lab_section_sample_type',
            ['sample_type_id'], { lab_section_id => 3 } )->flat; # warn Dumper $sample_type_ids;
		$dbix->insert('lab_test_sample_type',
			{ lab_test_id => $lab_test_id, sample_type_id => $_ }) for @$sample_type_ids;        
    }
    # new screen terms requests molecular lab_tests:
    $dbix->insert('screen_lab_test',
        { screen_id => 3, lab_test_id => 5 } # APML - is a Molecular test
    );
    $dbix->insert('screen_lab_test',
        { screen_id => 4, lab_test_id => 10 } # JAK2 - is a Molecular test
    );
    # new user to change reporter so can authorise:
    $dbix->insert('users', { username => 'user1' }); # only required field
    # change Flow lab_section 'has_test_sign_out' value:
    $dbix->update( 'lab_sections',
        { has_test_sign_out => 'yes' }, { section_name => 'Flow' }
    );
}

# 1) PNH exempt from final_diagnosis confirmation:
# screen request:
$mech->get_ok('/screen/=/1');                                 # print_and_exit();
{
    _do_screen(2,'PNH');                                      # print_and_exit();
}

# sign off result:
$mech->get_ok('/result/=/1');                                 # print_and_exit();
{
    _do_results_sign_off('flow_results');                     # print_and_exit();
}

# report & authorise record:
$mech->get_ok('/report/=/1');                                 # print_and_exit();
{
    _do_report(1);                                           #  print_and_exit();    
}

# should be status = complete:
is( _get_status_option(1), 5, 'OK: expected request status found' ); # print_and_exit(); 
#-------------------------------------------------------------------------------

# 2) CML interferon follow-up on LU sample - requires comfirmation:
# screen request so it can be reported:
$mech->get_ok('/screen/=/2');                                 # print_and_exit();
{
    _do_screen(3,'CML interferon follow-up');                 # print_and_exit();
}

# sign off result & enter result summary:
$mech->get_ok('/result/=/2');                                 # print_and_exit();
{
    _do_results_summary();                                    # print_and_exit();
}

# report record:
$mech->get_ok('/report/=/2');                                 # print_and_exit();
{
    _do_report(2);                                            # print_and_exit();    
}
    
=begin # changed timing of result summary - now only incomplete if AFTER auth time 
# should NOT be status = complete:
is( _get_status_option(2), 4, 'OK: expected request status found' ); # print_and_exit(); 

# re-report and check final_diagnosis box:
$mech->get_ok('/report/=/2');                                 # print_and_exit();
{
    _do_re_report(2);                                         # print_and_exit();    
}
=cut

# should be status = complete:
is( _get_status_option(2), 5, 'OK: expected request status found' ); # print_and_exit(); 
#-------------------------------------------------------------------------------

# 3) CML interferon follow-up on PB - exempt from confirmation:
_register_new_request(3);
$mech->get_ok('/screen/=/3');                                 # print_and_exit();
{
    _do_screen(3,'CML interferon follow-up');                 # print_and_exit();
}

# sign off result & enter result summary:
$mech->get_ok('/result/=/3');                                 # print_and_exit();
{
    _do_results_summary();                                    # print_and_exit();
}

# report record:
$mech->get_ok('/report/=/3');                                 # print_and_exit();
{
    _do_report(3);                                            # print_and_exit();    
}

# should be status = complete:
is( _get_status_option(3), 5, 'OK: expected request status found' ); # print_and_exit(); 
#-------------------------------------------------------------------------------

# 4) CMPD pres & follow-up on PB with JAK2 + CML tests - requires confirmation:
_register_new_request(4);
$mech->get_ok('/screen/=/4');                                 # print_and_exit();
{
    _do_screen(4,'CMPD pres & follow-up');                    # print_and_exit();
}
# request new lab_test and sign it off:
$mech->get_ok('/result/=/4');                                 # print_and_exit();
{
    $mech->form_name('flow_requests');
    $mech->tick('test_id', 2, 1);
    $mech->submit();                                          # print_and_exit();
    
    $mech->get_ok('/result/=/4');                             # print_and_exit();
    _do_results_sign_off('flow_results');                     # print_and_exit();
}

# sign off result & enter result summary:
$mech->get_ok('/result/=/4');                                 # print_and_exit();
{
    _do_results_summary();                                    # print_and_exit();
}

# report record:
$mech->get_ok('/report/=/4');                                 # print_and_exit();
{
    _do_report(4);                                            # print_and_exit();    
}

=begin # changed timing of result summary - now only incomplete if AFTER auth time 
# should NOT be status = complete:
is( _get_status_option(4), 4, 'OK: expected request status found' ); # print_and_exit();

# re-report and check final_diagnosis box:
$mech->get_ok('/report/=/4');                                 # print_and_exit();
{
    _do_re_report(4);                                         # print_and_exit();    
}
=cut    
# should now be status = complete:
is( _get_status_option(4), 5, 'OK: expected request status found' ); # print_and_exit(); 

#-------------------------------------------------------------------------------

# 5) CMPD pres & follow-up on PB & BMAT with JAK2 - requires confirmation:
_register_new_request(5, 'pb,bmat');
$mech->get_ok('/screen/=/5');                                 # print_and_exit();
{
    _do_screen(4,'CMPD pres & follow-up');                    # print_and_exit();
}

# sign off result & enter result summary:
$mech->get_ok('/result/=/5');                                 # print_and_exit();
{
    _do_results_summary();                                    # print_and_exit();
    
    # BMAT requests AUTO (histology) test:
    $mech->get_ok('/result/=/5');                             # print_and_exit();
    _do_results_sign_off('histology_results');                # print_and_exit();

    # AUTO = lab_test_id_9:
    $mech->get_ok('/result/=/5');                             # print_and_exit();
    _do_results_entry('histology_results','lab_test_id_9','foo'); # print_and_exit();
}

# report record:
$mech->get_ok('/report/=/5');                                 # print_and_exit();
{
    _do_report(5);                                            # print_and_exit();    
}

=begin # changed timing of result summary - now only incomplete if AFTER auth time 
# should NOT be status = complete:
is( _get_status_option(5), 4, 'OK: expected request status found' ); # print_and_exit();

# re-report and check final_diagnosis box:
$mech->get_ok('/report/=/5');                                 # print_and_exit();
{
    _do_re_report(5);                                         # print_and_exit();    
}
=cut    
# should now be status = complete:
is( _get_status_option(5), 5, 'OK: expected request status found' ); # print_and_exit(); 

#-------------------------------------------------------------------------------

# 6) CMPD pres & follow-up on PB with JAK2 only - exempt from confirmation:
_register_new_request(6);
$mech->get_ok('/screen/=/6');                                 # print_and_exit();
{
    _do_screen(4,'CMPD pres & follow-up');                    # print_and_exit();
}

# sign off result & enter result summary:
$mech->get_ok('/result/=/6');                                 # print_and_exit();
{
    _do_results_summary();                                    # print_and_exit();
}

# report record:
$mech->get_ok('/report/=/6');                                 # print_and_exit();
{
    _do_report(6);                                            # print_and_exit();    
}

# should be status = complete:
is( _get_status_option(6), 5, 'OK: expected request status found' ); # print_and_exit();


#-------------------------------------------------------------------------------

# 7) CMPD pres & follow-up on PB with JAK2 + flow test + delayed result summary:
_register_new_request(7);
{    
    $mech->get_ok('/screen/=/7');                             # print_and_exit();
    _do_screen(4,'CMPD pres & follow-up');                    # print_and_exit();

    $mech->get_ok('/result/=/7');                             # print_and_exit();
    $mech->form_name('flow_requests');
    $mech->tick('test_id', 3, 1); # flow CML
    $mech->submit();                                          # print_and_exit();
}

# sign off CML test, leaving JAK2 & result summary outstanding:
$mech->get_ok('/result/=/7');                                 # print_and_exit();
{
    _do_results_summary('flow');                              # print_and_exit();
}

# report record:
$mech->get_ok('/report/=/7');                                 # print_and_exit();
{
    _do_report(7, 'confirm_outstanding_tests');               # print_and_exit();    
}
# check is not complete:
is( _get_status_option(7), 4, 'OK: expected request status found' ); # print_and_exit();

# sign off result & enter result summary:
$mech->get_ok('/result/=/7');                                 # print_and_exit();
{
    sleep 1; # to ensure datetime result summary always > datetime authorisation
    _do_results_summary();                                    # print_and_exit();
}
# re-report, forget to check final_diagnosis box:
$mech->get_ok('/report/=/7');                                 # print_and_exit();
{
    $mech->form_name('reportForm');
    $mech->submit_form();                                    # print_and_exit();
    $mech->submit_form(form_name => 'reportForm') if $spell_check_required;
    # should NOT be status = complete:
    is( _get_status_option(7), 4, 'OK: expected request status found' );
}
# re-report and check final_diagnosis box:
$mech->get_ok('/report/=/7');                                 # print_and_exit();
{
    _do_re_report(7);                                         # print_and_exit();    
    # should now be status = complete:
    is( _get_status_option(7), 5, 'OK: expected request status found' );
}
}

sub _register_new_request {
    my $request_number = shift;
    my $specimen = shift || 'pb';
    
    $mech->get_ok('/request/add_new/2');                      # print_and_exit();
    
    $mech->submit_form(
        fields => {
            request_number => $request_number,
            referrer_code => 'C9999998',
            specimen => $specimen,
        }
    );                                                        # print_and_exit();
} 

sub _get_status_option {
    my $id = shift;
    
    my $status_option_id = $dbix->query(
        q!select status_option_id from requests where id = ?!, $id
    )->list;
        
    return $status_option_id;
}

sub _do_screen {
    my ($screen_id, $screen) = @_;
    
    $mech->form_name('initialScreen'); # 1st one is patient notes

    $mech->field(screen_id => $screen_id);
    $mech->field(option_id => 1);
    $mech->submit(); 
    
    $mech->text_contains(
       'Screened as ' . $screen,
        'OK: expected screen term found',
    );
}

sub _do_results_summary {
    my $section = shift || 'molecular';
    my $text = "$section result summary";
    
    $mech->form_name($section . '_results');
    $mech->field(results_summary => $text);
    $mech->tick('complete_all_tests', 1, 1);
    
    $mech->submit();                                        
    
    $mech->has_tag_like(
        td => qr($text),
        'OK: expected text found',
    );    
}

sub _do_results_sign_off {
    my $form_name = shift;
    
    $mech->form_name($form_name);
    $mech->tick('complete_all_tests', 1, 1);
    
    $mech->submit(); 
}

sub _do_results_entry {
    my ($form_name, $test_id, $result) = @_;
    
    $mech->form_name($form_name);
    $mech->field($test_id => $result);
    $mech->submit();
}

sub _do_report {
    my $id = shift; # warn $id;
    my $has_oustanding_tests = shift; # optional

    my $report = _get_report();
    $report->{confirm_outstanding_tests} = 1 if $has_oustanding_tests;

    $mech->form_name('reportForm');
    $mech->submit_form(fields => $report);                   #  print_and_exit();
    $mech->submit_form(form_name => 'reportForm') if $spell_check_required;

    my $msg = get_messages('action')->{edit_success};
    $mech->has_tag_like(
        p => qr($msg),
        'OK: record updated successfully',
    );                                             # print_and_exit() if $id == 7;

    # have to manually change reporter ID or self-auth refused:
    $dbix->update(
        'request_history',
        { user_id => 2 }, 
        { request_id => $id, action => 'reported' }
    );
    
    # skip pre-auth check:
    $mech->get_ok("/report/=/$id?pre-authorisation-check=1"); # print_and_exit();

    $mech->form_name('reportForm');
    $mech->field( authorise => 1 );
    $mech->tick('confirm_outstanding_tests', 1, 1) if $has_oustanding_tests;   
    $mech->submit_form();                         # print_and_exit() if $id == 7;
    $mech->submit_form(form_name => 'reportForm') if $spell_check_required;

    $mech->has_tag_like(
        p => qr($msg),
        'OK: record updated successfully',
    );                                            # print_and_exit() if $id == 7;
    
    $mech->text_contains(
        'Authorised by Admin_fname Admin_lname',
        'OK: expected authoriser details found',
    );
}

sub _do_re_report {
    my $id = shift;

    $mech->form_name('reportForm');
    $mech->tick('final_diagnosis', 1, 1);                     
    $mech->submit_form();                                          # print_and_exit();
    $mech->submit_form(form_name => 'reportForm') if $spell_check_required;
}

sub _get_report {
    return {
        status  => 'default',
        biopsy_site => 'anatomical details',
        confirm_outstanding_results => 1, # in case needed by sample type
        clinical_details => 'some details here',
        gross_description => 'gross description here',
        comment => 'morphology comment here',
        specimen_quality => 'adequate',
        diagnosis_id => 1,
    };
}