#!/usr/bin/perl

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

use strict;
use warnings;

use DateTime;
use POSIX;

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

=begin # tests:
1) register new guest-level user
=cut

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

my $mech = get_mech();

my $dbh;

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

warn $@ if $@;

foreach( qw// ) {
    drop_and_recreate($_);
}

do_login();

my %users = (
    guest => {
        id => 2, # 2nd record in users table
        username => 'guest',
        last_name => 'guest',
        first_name => 'guest',
        userid => 'guest.guest',
        password => 'guessed',
        user_location_id => 1,
        designation => 'test user - guest',
        email => 'guest@example.com',
        group_id => 2, # guest
        active => 'yes',
    },
    bms => {
        id => 3,
        username => 'bms',
        last_name => 'bms',
        first_name => 'bms',
        userid => 'bms.bms',
        password => 'bee-em-ess',
        user_location_id => 1,
        designation => 'test user - intermediate',
        email => 'bms@example.com',
        group_id => 3, # bms
        active => 'yes',
    },
);

# these all need 'administration' permissions:
my @admin_actions = qw(
    /admin
    /admin/lab_test
    /admin/lab_section
    /config/settings
    /admin/screen_term
    /admin/screen_test
    /config/specimens
    /config/clinicians
    /config/diagnoses
    /config/diagnostic-categories
    /config/general-practitioners
    /config/trials
    /config/error-codes
    /config/referral-sources
    /config/parent-organisations
    /config/request-audit-options
    /config/request-audit-categories
);

# everyone alowed:
my @all_allowed = qw(
    /search
    /history/load/1
);

# need 'edit_pid' functions:
my @edit_pid = qw(
    /patient/edit_patient/1
    /patient/edit_case/1
    /request/delete_request/1
);

# need 'register' functions:
my @register_functions = qw(
    /patient/select_patient/1
    /register/patient_search?name=brown
    /request/add_new/1
);

# need 'report' functions
my @report_functions = qw(
    /screen/load/1
);

# register new users:
foreach (keys %users) {
    create_and_test_new_user($users{$_});
}

# can default test-user do all functions?
{
    for my $url ( @admin_actions, @all_allowed, @edit_pid, @register_functions,
            @report_functions ) {
        $mech->get_ok($url);
        lacks_forbidden_action();
    } # print_and_exit();

}

# now logout and back in as new guest user:
{
    do_logout();

    $mech->submit_form(
        fields => {
            authen_username => $users{guest}->{userid},
            authen_password => $users{guest}->{password},
        },
    );                                       # print_and_exit();

    # check we've logged in as guest user:
	$mech->has_tag_like(
		span => qr($users{guest}->{first_name} $users{guest}->{last_name})i,
        'user logged in successfully',
	);
}

# for testing purposes:
#$mech->get_ok('/patient');                print_and_exit();

# test search link:
{
    $mech->has_tag_like(
        a => qr/search/i,
        'OK: search link is available',
    );                                       # print_and_exit();

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

    lacks_forbidden_action();               # print_and_exit();
}

# test register_link:
{
    test_out( 'not ok 1 - OK: register link not available' );
    test_fail( +1 );
    $mech->has_tag_like( a => qr/register/i, 'OK: register link not available' );
    test_test( 'Handles unfindable tag by content regexp' );

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

    has_forbidden_action();
}

# test admin link:
{
    $mech->content_lacks(
        'Admin</a>',
        'OK: admin link not available',
    );                                       # print_and_exit();

    $mech->get_ok('admin');               # print_and_exit();

    has_forbidden_action();                    # print_and_exit();
}

SKIP: {
    skip('actions not implemented yet',1);
    #test WorkList link:
    #test PrintRun link:
}

# test permissions:
{
    for my $url (@all_allowed) {
        $mech->get_ok($url);
        lacks_forbidden_action();
    }

    for my $url (@admin_actions, @edit_pid, @register_functions, @report_functions) {
        $mech->get_ok($url);
        has_forbidden_action();
    } # print_and_exit();
}

# now logout and back in as new intermediate user:
{
    do_logout(); # print_and_exit();

    $mech->submit_form(
        fields => {
            authen_username => $users{bms}->{userid},
            authen_password => $users{bms}->{password},
        },
    );                                        # print_and_exit();

    # check we've logged in as intermediate user:
	$mech->has_tag_like(
		span => qr($users{bms}->{first_name} $users{bms}->{last_name})i,
        'user logged in successfully',
	);
}

# test register_link:
{
    $mech->has_tag_like(
        a => qr/register/i,
        'OK: register link is available',
    );                                       # print_and_exit();

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

    lacks_forbidden_action();
}

# test admin link:
{
    test_out( 'not ok 1 - OK: admin link not available' );
    test_fail( +1 );
    $mech->has_tag_like( a => qr/admin/i, 'OK: admin link not available' );
    test_test( 'Handles unfindable tag by content regexp' );

    $mech->get_ok('admin');               # print_and_exit();

    has_forbidden_action();                    # print_and_exit();
}

# test permissions:
{
    for my $url (@all_allowed, @register_functions) {
        $mech->get_ok($url);
        lacks_forbidden_action();
    }

    for my $url (@admin_actions, @edit_pid, @report_functions) {
        $mech->get_ok($url);
        has_forbidden_action();
    } # print_and_exit();
}

# load record to test request_links:
$mech->get_ok('/search/load/1');                            # print_and_exit();
{
    # only History link should be available:
    $mech->has_tag(
        a => 'History',
        "OK: active History link present",
    );

    for my $item ( qw/Results Report Errors PhoneLog Print/ ) { # Delete & Unlock moved
        test_out( 'not ok 1 - foo' );
        test_fail( +1 );
        $mech->has_tag( a => $item, 'foo' );
        test_test( "OK: active $item link not present" );

#        $mech->content_contains( # changed - inactive links not displayed anymore
        $mech->content_lacks(
            $item,
            "OK: inactive $item link NOT present",
        );
    }
}

do_logout();

sub has_forbidden_action {
    $mech->content_contains(
        'Permission Denied',
        'OK: forbidden action',
    );                                       # print_and_exit();
}

sub lacks_forbidden_action {
    $mech->content_lacks(
        'Permission Denied',
        'OK: permitted action',
    );                                       # print_and_exit();
}

sub create_and_test_new_user {
    my $user = shift;

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

    $mech->form_name('user_update');
    $mech->submit_form(fields => $user);             # print_and_exit();

    # check we have success message:
    $mech->content_contains(
        get_messages('admin')->{user}->{create_success},
        'OK: new user created successfully',
    );                                              # print_and_exit();

    # retrieve new user (no need - changed update_user_details() to automatically retrieve):
    # $mech->submit_form(fields => { id => $user->{id} });          print_and_exit();

    # check we have new user loaded:
    $mech->content_contains(
        $user->{email},
        'OK: new user details loaded',
    );                                        # print_and_exit();

    ### check default settings:
    $mech->content_contains(
        '<span class="maroon">DEFAULT</span>',
        'OK: default settings used',
    );                                        # print_and_exit();
}
