package API::Util;
use strict;
use warnings;

use lib '/app/tools/appuser/lib';
use AppUser::DB::Item::User;

#use lib '/app/tools/api/lib';
#use API::Response;
#use API::DB::Item::PortalPayee;
#use API::DB::Item::PasswordRecovery;

use lib '/app/tools/common/lib';
use Common::RSApp;
use Common::Util;

use constant kInvalidPassword => 'Password does not meet policy';

# Validate a password and ensure that it meets our password policy.
# If a user object (AppUser::DB::Item::User) is passed in, then we'll
# also check if the password is being set the same as the user's email,
# or if the password is being set the same as the existing password
#
# Returns an HTTP status code with the validation status
#   200 - VALID: password OK
#   405 - FAIL: Cannot use email address as password
#   406 - FAIL: Cannot re-use existing password
#   407 - FAIL: Password must be between 8 and 20 characters
#   408 - FAIL: Password cannot be blank
#
sub validatePassword {
    my $self     = shift;
    my $password = shift;
    my $userObj  = shift;

    my $emsg = '';

    my $valid = 200;
    if ($password) {

        # RSD-125: Password cannot match username, and must be 8-20 characters in length
        if ($userObj) {
            if ( $password eq $userObj->email ) {
                Common::Log::Print( "Warning: attempted to set password to user email '" . $userObj->email . "'" );
                $emsg  = "Cannot use email address as password";
                $valid = 405;
            }

            # Check if user is trying to reuse old password
            my $cdbo = Common::RSApp::GetCommonDB();
            my $hashed_password = AppUser::DB::Item::User->HashPassword($password);
            my $sql = "SELECT IF(" . $cdbo->DBQuote($hashed_password) . "=password,1,0) FROM user WHERE user_id = " . $userObj->user_id;
            my $sth  = $cdbo->DoCmd($sql);
            my ($passwordExists) = $sth->fetchrow_array();
            if ($passwordExists) {
                Common::Log::Print( "Warning: attempted to re-use existing password for user email '" . $userObj->email . "'" );
                $emsg  = "Cannot re-use existing password";
                $valid = 406;
            } elsif ( AppUser::DB::Item::User->HasPreviousPassword( $userObj->user_id, $password ) ) {
                Common::Log::Print( "Warning: attempted to re-use prevous password for user email '" . $userObj->email . "'" );
                $emsg  = "Cannot re-use previous password";
                $valid = 406;
            }
        }

        if ( $valid == 200 ) {
            my $plen = length($password);
            if ( $plen < 12 ) {
                Common::Log::Print("Warning: password length $plen is invalid");
                my $m = "Password must be at least 12 characters";
                $emsg = ($emsg) ? "$m; $emsg" : $m;
                $valid = 407;
            }
        }

        # Password is valid at this point

    } else {
        Common::Log::Print("Warning: password cannot be blank");
        $emsg  = "Password cannot be blank";
        $valid = 408;
    }

    return ( $valid, $emsg );
}

sub cleanName {
    my $self = shift;
    my $name = shift;

    my $clientName = $name;

    # Replace '&' with 'and' - the normal clean function doesn't do that.
    #
    $clientName =~ s/ \& / and /g;
    $clientName = Common::Util::clean_name($clientName);

    return $clientName;
}

# Transform MySQL timestamp that can be lexically compared
sub to_comparable {
    my $self = shift;
    my $date = shift;
    my ($Y,$m,$d, $H,$M,$S) = $date =~ m{^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})\z} or die;
    return "$Y$m$d$H$M$S";
}

1;
