#!/usr/bin/perl

use Test::WWW::Mechanize::CGIApp;

use strict;
use warnings;

use DateTime;
use POSIX;

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

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

    use DateTime;
    DateTime->DefaultLocale('en_GB');
}

my $mech = get_mech();

my $dbh;

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

warn $@ if $@;

do_login();

=begin # tests:
1) test invalid dobs (31/Feb, future date, 2-digit yr, non-leap-yr 29/Feb)
2) test valid leap-yr 29/Feb as dob
3) test today as dob
4) test valid last_name
5) test valid last_name & first_name
6) submit invalid nhs_no in patient_no field & check it's loaded into unit_number field 
6) submit valid nhs_no in patient_no field & check it's loaded into nhs_number field
7) submit registration form with each of required fields missing
8) submit registration form with unit_number registered to different patient
9) submit registration form with complete details & minimal details
=cut

my %patient = (
    last_name   => 'bloggs',
    first_name  => 'joe',
    middle_name => 'david',
    day         => 31,
    month       => 1,
    year        => 1960,
    nhs_no      => '0123456789',
    dob         => '31-01-1960',
    sex         => 'M',
    unit_no     => 1011, # already exists in test_data.sql
);

my $dt = DateTime->now; # warn $dt;

# test invalid dobs:
$mech->get_ok('/register'); # print_and_exit();

{
    $mech->submit_form(
        fields => {
            day   => 31,
            month => 2,
            year  => 2007,
        }
    );                                                       # print_and_exit();
    
    has_dfv_errors();

    $mech->has_tag_like(
        span => qr(invalid),
        'OK: invalid date detected',
    );                                                       # print_and_exit();

    # 1 yr in future:
    $mech->submit_form(
        fields => {
            day   => 2,
            month => 2,
            year  => $dt->year + 1,
        }
    );                                                       # print_and_exit();

    has_dfv_errors();
    
    $mech->has_tag_like(
        span => qr(invalid),
        'OK: invalid date detected',
    );                                                       # print_and_exit();

    # 2-digit yr:
    $mech->submit_form(
        fields => {
            day   => 2,
            month => 2,
            year  => 66,
        }
    );                                                       # print_and_exit();

    has_dfv_errors();
    
    $mech->has_tag_like(
        span => qr(invalid),
        'OK: invalid date detected',
    );                                                       # print_and_exit();

    # invalid 29th Feb - non-leap yr:
    $mech->submit_form(
        fields => {
            day   => 29,
            month => 2,
            year  => 2003,
        }
    );               # print_and_exit();

    has_dfv_errors();
    
    $mech->has_tag_like(
        span => qr(invalid),
        'OK: invalid non-leap-yr 29th Feb detected',
    );                                                       # print_and_exit();

    # valid 29th Feb - leap yr:
    $mech->submit_form(
        fields => {
            day   => 29,
            month => 2,
            year  => 2004,
        }
    );                                                       # print_and_exit();

    $mech->content_lacks(
        get_messages('dfv_errors'),
        'valid leap-yr 29th Feb passed OK',
    );
}

$mech->get_ok('/register'); # print_and_exit();

# valid dob:
{
    # handles today OK:
    $mech->submit_form(
        fields => {
            day   => $dt->day,
            month => $dt->month,
            year  => $dt->year,
        }
    );             #  print $fh $mech->content;

    lacks_dfv_errors();

    my $today = $dt->dmy;
    
    $mech->content_contains(
        "Found 0 records matching dob=$today",
        'OK: searched on correct dob value',
    );

    $mech->back;                                             # print_and_exit();

    # submit valid dob:
    $mech->submit_form(
        fields => {
            day   => $patient{day},
            month => $patient{month},
            year  => $patient{year},
        }
    );                                                       # print_and_exit();

    $mech->content_contains(
        "Found 0 records matching dob=$patient{dob}",
        'OK: searched on correct dob value',
    );

    # dates re-loaded back into form:
    is( $mech->value('day',   1), $patient{day},   'value for day reloaded ok' );
    is( $mech->value('month', 1), $patient{month}, 'value for month reloaded ok' ); 
    is( $mech->value('year',  1), $patient{year},  'value for year reloaded ok' );   
}                                                            # print_and_exit();

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

# submit valid name (single value):
{
    $mech->submit_form(
        fields => {
            name  => $patient{last_name},
            day   => $patient{day},
            month => $patient{month},
            year  => $patient{year},
        },
    );                                                       # print_and_exit();
    
    $mech->content_contains(
        "Found 0 records matching name=$patient{last_name} & dob=$patient{dob}",
        'OK: searched on correct last_name & dob values',
    );
    
    is( $mech->value('last_name', 1), $patient{last_name},  'value for last_name loaded ok' );
    is( $mech->value('first_name', 1), '',  'value for first_name loaded ok' );
}

$mech->back;                                                 # print_and_exit();

# submit valid name (double value):
{
    my ($last_name,$first_name,$dob) = @patient{ qw(last_name first_name dob) };
    
    $mech->submit_form(
        fields => {
            name => join ',', $last_name, $first_name,
        },
    );                                                       # print_and_exit();

    $mech->content_contains(
         "Found 0 records matching name=$last_name,$first_name",
        'OK: searched on correct last_name & first_name values',
    );

    is( $mech->value('last_name', 1),  $last_name,  'value for last_name loaded ok' );
    is( $mech->value('first_name', 1), $first_name,  'value for first_name loaded ok' );
}

$mech->back;                                                 # print_and_exit();

# submit patient_no that's not a valid nhs_number:
{
    my $patient_no = '0123456787';

    $mech->submit_form(
        fields => {
            patient_no => $patient_no,
        },
    );                                                       # print_and_exit();

    my ($last_name,$first_name,$dob) = @patient{ qw(last_name first_name dob) };

    $mech->content_contains(
         "Found 0 records matching patient_no=$patient_no",
        'OK: searched on correct patient_no value',
    );
    
    is( $mech->value('unit_number', 1), $patient_no, 'value for patient_no loaded into unit_number field ok' );
    is( $mech->value('nhs_number',  1), '',  'ok: value for patient_no not loaded into nhs_number field' );
}                                                            # print_and_exit();

$mech->back;

# submit patient_no that's IS a valid nhs_number:
{
    my ($last_name,$first_name,$nhs_no, $dob) = @patient{ qw(last_name first_name nhs_no dob) };
    
    $mech->submit_form(
        fields => {
            patient_no => $nhs_no,
        },
    );                                                       # print_and_exit();
    
    $mech->content_contains(
         "Found 0 records matching patient_no=$nhs_no",
        'OK: searched on correct patient_no value',
    );
    
    is( $mech->value('nhs_number',  1), $nhs_no, 'value for patient_no loaded into nhs_number field ok' );
    is( $mech->value('unit_number', 1), '',  'ok: value for patient_no not loaded into unit_number field' );
}

# ok, tested all parsing functions, reload new form & start again
$mech->get_ok('/register');
    
{
    my ($last_name,$first_name,$middle_name,$nhs_no,$sex,$day,$month,$year,$unit_no)
        = @patient{ qw(last_name first_name middle_name nhs_no sex day month year unit_no) };

    $mech->submit_form(
        fields => {
            name => join ',', $last_name, $first_name,
        },
    );                                                       # print_and_exit();

    # submit incomplete form:
    $mech->submit_form();                                    # print_and_exit();

    has_dfv_errors();
    has_missing();
    has_formvalidator_error( get_messages('require_one') );  # print_and_exit();

    # add nhs_number to clear missing require_one field:
    $mech->submit_form(
        fields => {
            nhs_number => $nhs_no,
        },
    );                                                       # print_and_exit();

    has_dfv_errors();
    has_missing();

    is( $mech->value('nhs_number', 1), $nhs_no, 'NHS number OK' );

    # add gender:
    $mech->field('gender', $sex); # $mech->set_visible( [ radio => 'M' ] );

    $mech->submit;
    
    has_dfv_errors();
    has_missing();
    
    is( $mech->value('gender', 1), $sex, 'Gender value OK' ); # print_and_exit();

    # add dob :
    $mech->submit_form(
        fields => {
            day   => $day,
            month => $month,
            year  => $year,
        }
    );                                                       # print_and_exit();

    is( $mech->value('day',   1), $day,   'value for day reloaded ok' );  # print_and_exit();
    is( $mech->value('month', 1), $month, 'value for month reloaded ok' );  # print_and_exit(); #
    is( $mech->value('year',  1), $year,  'value for year reloaded ok' );  # print_and_exit(); #
    
    has_dfv_errors();
    has_missing();                                           # print_and_exit();

    # add source_id to clear missing data msg:
    $mech->field('referral_source_id',1);
    
    # add (duplicate) unit_number & middle_name to complete all fields:
    $mech->field('unit_number', $unit_no);
    $mech->field('middle_name', $middle_name);               # print_and_exit();

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

    $mech->content_contains(
         'Potential duplicate record. Unit No. and/or NHS No. matches',
        'OK: potential duplicate record detected',
    );
    
    $mech->content_contains(
         "<strong>$unit_no</strong>",
        'OK: potential duplicate unit_number highlighted detected',
    );
    
    # increment unit number & resubmit:
    $mech->field('unit_number', $unit_no +1);
    
    $mech->submit_form();                                    # print_and_exit();

    # check registration OK:
    $mech->content_contains(
         'Request &raquo; New',
        'new patient registered OK',
    );

    my $first_names = join ' ', ($first_name, $middle_name);
    my $formatted_dob = DateTime->new(
        year => $year,
        month => $month,
        day => $day,
        formatter => get_formatter()
    );

    my $i=0;
    my $output = 'OK: patient demographics field [%s] detected';

    # check all fields detected OK:
    foreach ( uc $last_name, $nhs_no, $unit_no +1, $formatted_dob, $sex) {
        $mech->content_contains(
             "<td>$_</td>",
            sprintf $output, ++$i,
        );
    }
    foreach ( $first_name, $middle_name ) {
        $mech->content_like(
            qr(<span>$_</span>)i,
            sprintf $output, ++$i,
        );
    }
}                                                            # print_and_exit();

# check can register with minimum fields:
$mech->get_ok('/register'); # print_and_exit();
{    
    my ($last_name,$first_name,$middle_name,$nhs_no,$sex,$day,$month,$year,$unit_no)
        = @patient{ qw(last_name first_name middle_name nhs_no sex day month year unit_no) };

    $mech->submit_form(
        fields => {
            name => $last_name,
        },
    );                                                       # print_and_exit();
    
    $mech->content_contains(
         "Found <b>1</b> record matching <b>name=$last_name</b>",
        'OK: found 1 matching record',
    );

    # want to create new patient so follow 'new patient' link:
    $mech->follow_link_ok(
        # {n => 8}, "Logout $_ via eighth link on page",
        { url_regex => qr/patient/i, },
        'follow "new patient" link',
    );                                                       # print_and_exit();
    
    # change day so it's different patient:
    $day--;

    $mech->submit_form(
        fields => {
            first_name => $first_name,
            referral_source_id => 1,
            gender => $sex,
            day   => $day,
            month => $month,
            year  => $year,
        },
    );                                                       # print_and_exit();

    # check we have 'require_one' error message:
    has_formvalidator_error( get_messages('require_one') );

    # increment unit_number so it's unique:
    $unit_no++;
    $mech->field('unit_number', $unit_no);
    $mech->submit_form();                                    # print_and_exit();
    
    my $formatted_dob = DateTime->new(
        year  => $year,
        month => $month,
        day   => $day,
        formatter => get_formatter()
    );

    my $i=0;
    my $output = 'OK: patient demographics field [%s] detected';

    foreach ( uc $last_name, $unit_no, $formatted_dob, $sex) {
        $mech->content_contains(
             "<td>$_</td>",
            sprintf $output, ++$i,
        );
    }

    # check we have a NULL field (for nhs_number):
    $mech->content_contains(
        q!<span class="grey">[NULL]</span>!,
        'OK: NULL (nhs_number) field detected'
    );                                                      #  print_and_exit();
}

do_logout();
