#!/usr/bin/perl

# just testing for dfv errors using LIMS::Validation profiles:

use Test::WWW::Mechanize::CGIApp;
use Data::Dumper;

use strict;
use warnings;

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

=begin: tests:
1) error_codes profile
2) edit error_code
3) specimens profile
4) edit sample_code
5) referral_sources profile (new hospital)
6) edit hospital referral_source
7) referral_sources profile (new practice)
8) edit practice referral_source
9) new_clinicians profile
10) edit_referrer profile
11) diagnostic_categories profile
12) edit diagnostic_category
13) diagnoses profile
14) edit diagnosis
15) trials profile
16) edit new trial
17) parent_organisations profile
18) edit parent_organisation
19) request_audit_categories profile
20) edit category
21) request_audit_options profile
22) edit request_option
=cut

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

my $mech = get_mech();

do_login();

my $dbh;

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

warn $@ if $@;

# error_codes profile:
$mech->get_ok('/config/error-codes');                         # print_and_exit();
{
    my %new_error = (
        code => 'D',
        description => 'third error',
        active => 'yes',
    );
    
    test_missing_required(\%new_error);                       # print_and_exit();
    
    # add 'is_unique' - can't include in %new_error as it's optional in val profile:
    $mech->field(is_unique => 'yes');

    # make code duplicate:
    $mech->field(code => 'B');
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    has_duplicate();
    
    # make code unique:
    $mech->field(code => 'D');
    $mech->submit_form();                                     # print_and_exit();

    lacks_dfv_errors();
    lacks_duplicate();
}

# edit error_code:
$mech->get_ok('/config/error-codes/edit/2');                 #  print_and_exit();
{
    # edit code to value already used:
    $mech->field( code => 'A' );
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    has_duplicate();

    # revert code to original:
    $mech->field( code => 'B' );
    # modify description:
    $mech->field( description => 'modified description');
    $mech->submit_form();                                     # print_and_exit();
    
    lacks_dfv_errors();
    lacks_duplicate();
}

# specimens profile:
$mech->get_ok('/config/specimens');                           # print_and_exit();
{
    my %new_specimen = (
        sample_code => 'LF U', # invalid - has spaces
        description => 'lymph node, fixed & unfixed',
        sample_type_id => [1,2],
        active => 'yes',
    );
    
    test_missing_required(\%new_specimen);                    # print_and_exit();
    
    $mech->submit_form(fields => \%new_specimen);             # print_and_exit();

    has_dfv_errors();
    $mech->content_contains(
        dfv_format('single_word'),
        'OK: invalid format detetced',
    );                                                        # print_and_exit();

    # make sample_code duplicate:
    $mech->field(sample_code => 'PB');
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    has_duplicate();
    
    # make code unique:
    $mech->field(sample_code => 'LFU');
    $mech->submit_form();                                     # print_and_exit();

    lacks_dfv_errors();
    lacks_duplicate();
}

# edit sample_code:
$mech->get_ok('/config/specimens/edit/1');                   #  print_and_exit();
{
    # edit code to invalid value:
    $mech->field( sample_code => 'BMA T' ); # too long & has spaces
    $mech->submit_form();                                    #  print_and_exit();

    has_dfv_errors();
    $mech->content_contains(
        dfv_format('too_long'),
        'OK: field exceeded max length',
    );                                                        # print_and_exit();

    # edit code to invalid value - not too long but has spaces:
    $mech->field( sample_code => 'LF U' );
    $mech->submit_form();                                     # print_and_exit();

    has_dfv_errors();
    $mech->content_contains(
        dfv_format('single_word'),
        'OK: field exceeded max length',
    );                                                        # print_and_exit();
    
    # edit code to value already used:
    $mech->field( sample_code => 'BMA' );
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    has_duplicate();

    # revert code to original:
    $mech->field( sample_code => 'PB' );
    # modify description:
    $mech->field( description => 'modified description');
    $mech->submit_form();                                     # print_and_exit();
    
    lacks_dfv_errors();
    lacks_duplicate();
}

# referral_sources profile (new hospital):
$mech->get_ok('/config/referral-sources');                    # print_and_exit();
{
    my %new_hospital = (
        referral_type           => 'hospital',
        organisation_code       => 'TOO_LONG', # invalid
        display_name            => 'Newtown Royal',
        parent_organisation_id  => 1,
    );
    
    test_missing_required(\%new_hospital);                    # print_and_exit();
    
    $mech->submit_form(fields => \%new_hospital);             # print_and_exit();
    
    has_dfv_errors();
    $mech->content_contains(
        dfv_format('too_long'),
        'OK: field exceeded max length',
    );                                                        # print_and_exit();
    
    # make org_code < max length, but still invalid:
    $mech->field(organisation_code => 'ABC 01');
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    $mech->content_contains(
        dfv_format('single_word'),
        'OK: invalid format detected',
    );                                                        # print_and_exit();
   
    # duplicate organisation_code:
    $mech->field(organisation_code => 'ABC01');
    $mech->submit_form();                                     # print_and_exit();

    has_dfv_errors();
    has_duplicate();

    # org_code to valid:
    $mech->field(organisation_code => 'ABC02');
    # duplicate display_name:
    $mech->field(display_name => 'Newtown General Infirmary');    
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    has_duplicate();

    # submit valid form:
    $new_hospital{organisation_code} = 'ABC02';
    $mech->submit_form(fields => \%new_hospital);             # print_and_exit();

    lacks_dfv_errors();                                      #  print_and_exit();
    # check created OK:
    $mech->content_contains(
        get_messages('action')->{create_success},
        'OK: form validation succeeded',
    )
}

# edit hospital referral_source:
$mech->get_ok('/config/referral-sources/edit/1');             # print_and_exit();

{
    # duplicate organisation_code:
    $mech->field(organisation_code => 'ABC02');
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    has_duplicate();

    # revert organisation_code:
    $mech->field(organisation_code => 'ABC01');
    $mech->field(display_name => 'Newtown NHS Trust');
    $mech->submit_form();                                     # print_and_exit();
    
    lacks_dfv_errors();                                       # print_and_exit();
}

# referral_sources profile (new practice):
$mech->get_ok('/config/referral-sources');                    # print_and_exit();
{
    my %practice = (
        referral_type     => 'practice',
        organisation_code => 'B54321', 
        practice_name     => 'The New Surgery',
        practice_address  => 'Newtown', 
        practice_zip      => 'NT2 2NT',        
    );
    
    test_missing_required(\%practice);                        # print_and_exit();
    
    # no need to reproduce all tests in 'hospital' section:
    $mech->submit_form(fields => \%practice);                 # print_and_exit();

    lacks_dfv_errors();                                       # print_and_exit();
}

# edit practice referral_source:
$mech->get_ok('/config/referral-sources/edit/2');             # print_and_exit();
{
    # duplicate organisation_code:
    $mech->field(organisation_code => 'B54321');
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    has_duplicate();

    # revert organisation_code:
    $mech->field(organisation_code => 'B12345');
    $mech->field(display_name => 'The Old Surgery, Newtown, NT1 1NT');
    $mech->submit_form();                                     # print_and_exit();
    
    lacks_dfv_errors();                                       # print_and_exit();
}

# new_clinicians profile:
$mech->get_ok('/config/clinicians');                          # print_and_exit();
{
    my %new_clinician = (
        prefix                   => 'C',
        national_code            => '765 4321', # invalid - spaces
        surname                  => 'White',
        initials_1               => 'A',
        referral_source_id       => 1,
        hospital_department_code => 823,
    );
    
    # non-standard form submission (need to specify form name):
    test_missing_required(\%new_clinician, 'new_clinicians'); # print_and_exit();
   
    $mech->form_name('new_clinicians');
    $mech->submit_form(fields => \%new_clinician);            # print_and_exit();
    
    has_dfv_errors();
    has_invalid();
    
    # make national_code > max value:
    $mech->form_name('new_clinicians');
    $mech->field(national_code => 19_999_999);
    $mech->submit_form();                                     # print_and_exit();

    has_dfv_errors();
    $mech->content_contains(
        dfv_format('too_high'),
        'OK: invalid format detected',
    );                                                        # print_and_exit();
    
    # make national_code non-numeric:
    $mech->form_name('new_clinicians');
    $mech->field(national_code => 'C7654321');
    $mech->submit_form();                                     # print_and_exit();

    has_dfv_errors();
    $mech->content_contains(
        dfv_format('numbers_only'),
        'OK: invalid format detected',
    );                                                        # print_and_exit();
   
    # duplicate national_code:
    $mech->form_name('new_clinicians');
    $mech->field(national_code => 1_234_567);
    $mech->submit_form();                                     # print_and_exit();

    $mech->content_contains( # needs a db lookup to use actual message
        'WARNING: surname mis-match with existing record',
        'OK: surname mismatch on duplicate national_code detected',
    );                                                        # print_and_exit();
    
    # submit valid form:
    $mech->form_name('new_clinicians');
    $new_clinician{national_code} = 2_222_222;
    $mech->submit_form(fields => \%new_clinician);            # print_and_exit();

    lacks_dfv_errors();
    $mech->content_contains( 
        get_messages('admin')->{clinician}->{create_success},
        'OK: form validation succeeded',
    );                                                        # print_and_exit();    
}

# edit_referrer profile:
$mech->get_ok('/config/clinicians');                          # print_and_exit();
{
    # get all clinicians from referrers table:
    my $dbix = get_dbix();
    my $sql = q!select r.* from referrers r join referral_types t on r.referral_type_id
        = t.id where t.description = 'clinician'!;
    my @clinicians = $dbix->query($sql)->hashes; # warn Dumper \@clinicians;
    # need at least 2:
    die unless @clinicians >= 2;    
    
    my $first_clinician  = $clinicians[0];
    my $second_clinician = $clinicians[1];
    # don't need 'id':
    delete $first_clinician->{id}; # or get error in test_missing_required()
    
    $mech->form_name('find_referrer');
    $mech->field(name => $first_clinician->{name});
    $mech->submit();                                          # print_and_exit();
    
    $mech->content_contains( 'Edit', 'OK: record loaded' );
    
    $mech->follow_link( text => 'Edit', n => 1 );             # print_and_exit();
    
    test_missing_required($first_clinician);
    
    # duplicate national_code:
    $mech->field(national_code => $second_clinician->{national_code});
    $mech->submit();                                          # print_and_exit();
    
    has_dfv_errors();
    has_duplicate();
    
    # national_code format invalid:
    $mech->field(national_code => 'C12345678'); # too long
    $mech->submit();                                          # print_and_exit();

    has_dfv_errors();
    $mech->content_contains(
        dfv_format('referrer_code'),
        'OK: format error detected',
    );                                                        # print_and_exit();
    
    $mech->field(national_code => '1234567'); # no letter prefix
    $mech->submit();                                   # print_and_exit();

    has_dfv_errors();
    $mech->content_contains(
        dfv_format('referrer_code'),
        'OK: format error detected',
    );                                                        # print_and_exit();
    
    # revert national_code:
    $mech->field(national_code => $first_clinician->{national_code});
    # change name:
    $mech->field(name => 'White, CD');    
    # set active to 'no':
    $mech->field(active => 'no');
    $mech->submit();
    
    lacks_dfv_errors();                                       # print_and_exit();
    $mech->content_contains( 
        get_messages('admin')->{clinician}->{edit_success},
        'OK: record edit succeeded',
    );                                                        # print_and_exit();    
}

# diagnostic_categories profile:
$mech->get_ok('/config/diagnostic-categories');               # print_and_exit();
{
    my %category = (
        description => 'Myelodysplastic', # duplicate
        category_type => 'main',
        active => 'yes',
    );
    
    test_missing_required(\%category);                        # print_and_exit();
 
    $mech->submit_form(fields => \%category);                 # print_and_exit();
    
    has_dfv_errors();
    has_duplicate();

    $category{description} = 'Myeloproliferative'; 
    $mech->submit_form(fields => \%category);                 # print_and_exit();
    
    lacks_dfv_errors();
    lacks_duplicate();                                        # print_and_exit();
}

# edit diagnostic_category:
$mech->get_ok('/config/diagnostic-categories/edit/2');        # print_and_exit();
{
    # change name to duplicate:
    $mech->field(description => 'Myelodysplastic');                               
    $mech->submit_form();                                     # print_and_exit();

    has_dfv_errors();
    has_duplicate();                                          # print_and_exit();

    # revert name:
    $mech->field(description => 'Lymphoproliferative');
    # change type to 'sub':
    $mech->field(category_type => 'sub');
    $mech->submit_form();                                     # print_and_exit();

    lacks_dfv_errors();
    lacks_duplicate();
}

# diagnoses profile:
$mech->get_ok('/config/diagnoses');                           # print_and_exit();
{
    my %diagnosis = (
        name => 'RAEB', # duplicate
        diagnostic_category_id => 1,
        active => 'yes',
    );
    
    test_missing_required(\%diagnosis);                       # print_and_exit();
 
    # add optional icdo3 field:
    $diagnosis{icdo3} = '9983/3'; # icdo3 for RAEB
    $mech->submit_form(fields => \%diagnosis);               #  print_and_exit();
    
    has_dfv_errors();
    has_duplicate();

    $diagnosis{name} = 'RARS'; 
    $mech->submit_form(fields => \%diagnosis);                # print_and_exit();
    
    lacks_dfv_errors();
    lacks_duplicate();                                        # print_and_exit();
}

# edit diagnosis:
$mech->get_ok('/config/diagnoses/edit/3');                    # print_and_exit();
{
    # change name to duplicate:
    $mech->field(name => 'RAEB');                               
    $mech->submit_form();                                    #  print_and_exit();

    has_dfv_errors();
    has_duplicate();

    # revert name:
    $mech->field(name => 'RARS');
    # change icdo3 to RARS:
    $mech->field(icdo3 => '9982/3');
    $mech->submit_form();                                     # print_and_exit();

    lacks_dfv_errors();
    lacks_duplicate();
}

# trials profile:
$mech->get_ok('/config/trials');                              # print_and_exit();
{
    my %trial = (
        trial_name => 'NCRI: Myeloma X', # duplicate
        active => 'yes',
    );
    
    test_missing_required(\%trial);                           # print_and_exit();
 
    $mech->submit_form(fields => \%trial);                   #  print_and_exit();
    
    has_dfv_errors();
    has_duplicate();

    $trial{trial_name} = 'NCRI: Myeloma XI'; 
    $mech->submit_form(fields => \%trial);                    # print_and_exit();
    
    lacks_dfv_errors();
    lacks_duplicate();
} 

# edit new trial:
{
    my $trial_id = get_last_insert_id('clinical_trials');
    $mech->get_ok('/config/trials/edit/'.$trial_id);          # print_and_exit();

    # change name to duplicate:
    $mech->field(trial_name => 'NCRI: Myeloma X');                               
    $mech->submit_form();                                     # print_and_exit();

    has_dfv_errors();
    has_duplicate();

    # revert name:
    $mech->field(trial_name => 'NCRI: Myeloma XI');
    # change active to 'no':
    $mech->field(active => 'no');
    $mech->submit_form();                                     # print_and_exit();

    lacks_dfv_errors();
    lacks_duplicate();
}

# parent_organisations profile:
$mech->get_ok('/config/parent-organisations');               #  print_and_exit();
{
    my %parent_organisation = (
        parent_code  => 'A 123', # invalid - space
        description  => 'Newtown NHS Trust', # duplicate
        referral_type => 'hospital',
    );
    
    test_missing_required(\%parent_organisation);             # print_and_exit();
 
    $mech->submit_form(fields => \%parent_organisation);     #  print_and_exit();
    
    has_dfv_errors();
    # description:
    has_duplicate();                                          # print_and_exit();
    # parent_code:
    $mech->content_contains(
        dfv_format('single_word'),
        'OK: invalid format detected',
    );                                                        # print_and_exit();

    # switch duplicate to parent_code: 
    $mech->field(parent_code => 'ABC'); # duplicate
    # make description valid:
    $mech->field(description => 'Oldtown NHS Trust'); # valid
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    # parent_code:
    has_duplicate();
    $mech->content_lacks(
        dfv_format('single_word'),
        'OK: invalid format not detected',
    );                                                        # print_and_exit();

    # parent_code invalid:
    $mech->field(parent_code => 'TOO_LONG'); # invalid
    $mech->submit_form();                                     # print_and_exit();
    
    has_dfv_errors();
    $mech->content_contains( 
        dfv_format('too_long'),
        'OK: invalid field length detected',
    );                                                        # print_and_exit(); 

    # submit valid form:
    $mech->field(parent_code => 'DEF'); 
    $mech->submit_form();                                     # print_and_exit();
    
    lacks_dfv_errors();
} 

# edit parent_organisation:
$mech->get_ok('/config/parent-organisations/edit/6');         # print_and_exit();
{
    # change parent_code to duplicate:
    $mech->field(parent_code => 'ABC');                               
    $mech->submit_form();                                     # print_and_exit();

    has_dfv_errors(); 
    has_duplicate(); 

    # make parent_code valid:
    $mech->field(parent_code => 'EFG');
    # change description to duplicate:
    $mech->field(description => 'Newtown NHS Trust');
    $mech->submit_form();                                     # print_and_exit();

    has_dfv_errors(); 
    has_duplicate(); 

    # revert description:
    $mech->field(description => 'Oldtown NHS Trust');
    $mech->submit_form();                                     # print_and_exit();
    
    lacks_dfv_errors(); 
    lacks_duplicate();                                     
}

# request_audit_categories profile:
$mech->get_ok('/config/request-audit-categories');
{
    my %request_category = (
        description => 'cytopenia', # duplicate
    );   

    test_missing_required(\%request_category);

	$mech->submit_form(fields => \%request_category);         # print_and_exit();
    has_dfv_errors(); 
    has_duplicate();      

	$mech->field(description => 'general'); # valid
	$mech->submit_form();                               	  # print_and_exit();
	
    lacks_dfv_errors(); 
    lacks_duplicate();       
}

# edit category:
$mech->get_ok('/config/request-audit-categories/edit/2');     # print_and_exit();
{
	$mech->field(description => 'cytopenia'); # duplicate	
	$mech->submit_form();                               	  # print_and_exit();

    has_dfv_errors(); 
    has_duplicate();      

    # revert description:
    $mech->field(description => 'general');
	# set active to 'no':
    $mech->field(active => 'no');
	
    $mech->submit_form();
	
    lacks_dfv_errors(); 
    lacks_duplicate();    								      # print_and_exit();                                 
}

# request_audit_options profile:
$mech->get_ok('/config/request-audit-options');               # print_and_exit();
{
    my %request_option = (
        description => 'Anaemia', # duplicate
		category_id => 1,
    );   

    test_missing_required(\%request_option);
	
    $mech->submit_form(fields => \%request_option);           # print_and_exit();
    has_dfv_errors();
    has_duplicate();	
	
	# mis-spelled but valid entry
	$mech->field(description => 'Tird all the time'); # valid
    
	$mech->submit_form();								      # print_and_exit();
    lacks_dfv_errors(); 
    lacks_duplicate();       
}

# edit request_option:
$mech->get_ok('/config/request-audit-options/edit/2');        # print_and_exit();
{
    # description to duplicate:
    $mech->field(description  => 'Anaemia');                               
    $mech->submit_form();								      # print_and_exit();
    has_dfv_errors(); 
    has_duplicate(); 

    # revert description:
    $mech->field(description => 'Tired all the time');
    # change to new category entered above:
    $mech->field(category_id => 2);
	# set active to 'no':
    $mech->field(active => 'no');
    $mech->submit_form();								      # print_and_exit();
	
    lacks_dfv_errors(); 
    lacks_duplicate();                                     
}
