#!/usr/bin/perl

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

use strict;
use warnings;

use Data::Printer;
use Test::More tests => 37; #use Test::More 'no_plan';

=begin # tests:
0) tests mysql_supports_innodb in BEGIN block
1) login as default user
2) try to re-login as default user
3) logout
4) try to login with invalid pwd
5) test forgotten password with invalid email address
6) re-login & try to change password - submit too short value
7) submit mis-matched new pwds
8) submit correctly formatted new pwd
9) check logged out & redirected to login page
10) test new registration email link
11) test redirect generated by password reset function
12) test redirect_after_login (permitted destination url)
13) test redirect_after_login (disallowed destination url)
=cut

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

    # 1st test MySQL supports InnoDB tables:
    die 'no innodb support' unless mysql_supports_innodb();
}

my $test_username = 'admin_fname.admin_lname';
my $test_password = 'adm1n';

my $mech = get_mech();
my $dbix = get_dbix();

# login/logout tests handled by test-lib.pl

do_login($test_username, $test_password);                     # print_and_exit();

# invoke login again:
$mech->get_ok('/login');                                      # print_and_exit();

my $user_map = get_user_map($test_username); # warn Dumper $user_map;

# confirmed already logged in
$mech->content_contains(
    "You are logged in as $test_username",
    'confirmed already logged in',
);                                                            # print_and_exit();

# logout:
do_logout();

{ # test redirect_after_login (permitted destination url):
    my $permitted_url = 'search/notification/1';
    $mech->get_ok($permitted_url);

    # not logged in yet but check destination set correctly:
    $mech->form_name('login_form');
    like( $mech->field('destination'), qr{$permitted_url},
            'OK: intended destination detected');           #  print_and_exit();

    # login:
    $mech->submit_form(
        fields => {
            authen_username => $test_username,
            authen_password => $test_password,
        }
    );                                                        # print_and_exit();
    # print $mech->content; exit;
#   find urls containing request id:
    my @links = $mech->find_all_links( url_regex => qr{\w+/=/1} ); # eg screen/=/1
    # warn Dumper $_->url for @links; exit;
    $mech->links_ok( \@links, 'OK: nav links checked' );     #  print_and_exit();
}

# logout:
do_logout();

{ # test redirect_after_login (disallowed destination url):
    my $disallowed_redirect = 'report/update_report/1?diagnosis_id=1'; # don't need rest of url'
    $mech->get_ok($disallowed_redirect);                      # print_and_exit();
    $mech->form_name('login_form');
    is( $mech->field('destination'), '', 'OK: disallowed destination url'); # print_and_exit();

    # login:
    $mech->submit_form(
        fields => {
            authen_username => $test_username,
            authen_password => $test_password,
        }
    );                                                        # print_and_exit();

    # check no rediect:
    $mech->has_tag_like(
        h2 => qr/Search for record\(s\)/,
        'OK: search page loaded, no redirect'
    );                                                        # print_and_exit();
}

do_logout();

{ # test new registration email link:
    # epoch value of admin last_login:
    $dbix->select('users', 'last_login', { username => 'admin' })->into(my $date); # p $date;
    my $epoch = DateTime::Format::MySQL->parse_datetime($date)->epoch / 100; # p $epoch;
    my $url = '/?uid=1&first_login='.$epoch
        . '&authen_username='.$test_username
        . '&authen_password='.$test_password; # p $url;
    $mech->get_ok($url);                                      # print_and_exit();
    $mech->has_tag_like(
        h2 => qr/Search for record\(s\)/,
        'OK: logged in OK'
    );                                                        # print_and_exit();
}

do_logout();

{ # test redirect generated by password reset function:
    my $url = '/login?authen_username='.$test_username
        . '&authen_password='.$test_password
        . '&destination=/user/change_password/'.$test_password;
    $mech->get_ok($url);                                     # print_and_exit();
    $mech->has_tag( h2 => 'Change password', 'OK: change password page loaded');
    $mech->has_tag_like(
        p => qr/Now please change your password/,
        'OK: please change password',
    );
}

do_logout();

### select 1st form:
$mech->form_name('login_form');

# test invalid login:
$mech->submit_form( # WWW::Mechanize function
    fields => {
        authen_username => $test_username,
        authen_password => 'invalid',
    }
);                                                           # print_and_exit();

# invalid login detected:
$mech->content_contains(
    'Login failed (login attempt 1)',
    'catches invalid login',
);                                                            # print_and_exit();

# test forgotten password with invalid email:
$mech->form_name('forgotten_pwd');

my $email = 'noone@here.com';

$mech->submit_form(
    fields => {
        email_address => $email,
    }
);

$mech->content_contains(
    get_messages('login')->{email_not_found},
    'flash working - email not recognised',
);                                                           # print_and_exit();

# login & change pwd:
$mech->submit_form(
    fields => {
        authen_username => $test_username,
        authen_password => $test_password,
    }
);                                                           # print_and_exit();

# change password:
$mech->get_ok('/user/change_password');                      # print_and_exit();

# submit too short new pwd:
$mech->submit_form(
    fields => {
        old_password => 'adm1n',
        new_password => 'pwd',
        new_password_confirm => 'pwd',
    }
);                                                           # print_and_exit();

has_dfv_errors();

$mech->content_contains(
    get_messages('form_validator')->{user}->{new_password}->{LENGTH},
    'new password: incorrect length detected ok',
);

$mech->content_contains(
    get_messages('form_validator')->{user}->{new_password_confirm}->{LENGTH},
    'confirm new password: incorrect length detected ok',
);

# submit mis-matched new pwds:
$mech->submit_form(
    fields => {
        old_password => 'adm1n',
        new_password => 'new_pwd',
        new_password_confirm => 'new-pwd',
    }
);

has_dfv_errors();

$mech->content_contains(
    get_messages('form_validator')->{user}->{pwds}->{DUPLICATION},
    'new passwords do not match: detected ok',
);

# submit correct data:
$mech->submit_form(
    fields => {
        old_password => 'adm1n',
        new_password => 'new_pwd',
        new_password_confirm => 'new_pwd',
    }
);                                                           # print_and_exit();

$mech->content_contains(
    get_messages('user')->{pwd_change_success},
    'change password: success',
);

$mech->content_contains(
    'Please enter your login details',
    'redirect to login page: success',
);                                                            # print_and_exit();

# no need - already logged out:
# do_logout();
