package AppUser::ForgotPW::Form;

use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
use POSIX;

use lib '/app/tools/common/lib';
use RSApache::RSWebApp;

use lib '/app/tools/appuser/lib';
use AppUser::User::User;
use AppUser::User::Token;
use AppUser::ForgotPW::Command::ForgotPW;

use lib '/app/tools/rps/lib';
use Common::FormObject;
use Common::Email;
use base 'Common::FormObject';

use constant kEmptyTimestamp => '0000-00-00 00:00:00';

sub _init {
    my ( $self, %args ) = @_;

    $self->SUPER::_init(%args);

    $self->{Email}              = Common::FormObject::Scalar::EmailAddress->new();
    $self->{Token}              = Common::FormObject::Scalar::String->new();
    $self->{NewPassword}        = Common::FormObject::Scalar::String->new();
    $self->{NewPasswordConfirm} = Common::FormObject::Scalar::String->new();

    return $self;
}

sub validatePasswords {
    my $self = shift @_;

    my $valid = $self->SUPER::validate();

    if ( !$self->NewPassword() ) {
        $self->{NewPassword}->setError(Common::FormObject::kErrFieldBlank);
        $valid = 0;
    }

    if ( !$self->NewPasswordConfirm() ) {
        $self->{NewPassword}->setError(Common::FormObject::kErrFieldBlank);
        $valid = 0;
    }

    if ( $self->NewPassword() && $self->NewPasswordConfirm() ) {
        my $userObj = AppUser::User::User->new( email => $self->Email() );

        if ( defined $userObj && $userObj->UserID ) {

            my $tokenObj = AppUser::User::Token->new( email => $self->Email() );
            my $userID   = $userObj->UserID;

            if ( $tokenObj->IsValidToken( $self->Token() ) ) {

                if ( $self->NewPassword() eq $self->NewPasswordConfirm() ) {

                    # Make sure the password is valid

                    if ( AppUser::DB::Item::User->HasPreviousPassword( $userID, $self->NewPassword() ) ) {
                        $self->{NewPassword}->setError(Common::FormObject::kErrPasswordHistory);
                        $valid=0;
                    }

                    elsif ( $self->Email() eq $self->NewPassword() ) {
                        $self->{NewPassword}->setError(Common::FormObject::kErrPasswordUnsafe);
                        $valid=0;

                    }

                    elsif ( ! AppUser::DB::Item::User->IsValidPassword( $self->NewPassword()) ) {
                        $self->{NewPassword}->setError(Common::FormObject::kErrFieldInvalid);
                        $valid = 0;
                    }
                } else {

                    # the template is checking this too
                    $self->{NewPasswordConfirm}->setError(Common::FormObject::kErrPasswordMismatch);
                    $valid = 0;
                }
            } else {

                # this probably shouldn't happen, maybe it expired?
                $self->{Token}->setError(Common::FormObject::kErrTokenInvalid);
                $valid = 0;
            }
        } else {

            # this probably shouldn't happen
            $self->{Email}->setError(Common::FormObject::kErrEmailInvalid);
            $valid = 0;
        }

    }

    return $valid;
}

sub validateToken {
    my $self = shift @_;

    my $valid = $self->SUPER::validate();

    if ( $self->Token() ) {

        # validate token with user email
        my $userObj = AppUser::User::User->new( email => $self->Email() );
        if ( defined $userObj && lc( $userObj->Email ) eq lc( $self->Email() ) ) {
            my $tokenObj = AppUser::User::Token->new( email => $self->Email() );
            if ( !$tokenObj->IsValidToken( $self->Token() ) ) {
                $self->{Token}->setError(Common::FormObject::kErrTokenInvalid);
                $valid = 0;
            }
        } else {
            $self->{Email}->setError(Common::FormObject::kErrEmailInvalid);
            $valid = 0;
        }
    } else {
        $self->{Token}->setError(Common::FormObject::kErrTokenInvalid);
        $valid = 0;
    }

    return $valid;
}

sub validateEmail {
    my $self = shift @_;

    my $valid = $self->SUPER::validate();

    if ( $self->Email() ) {
        my $userObj = AppUser::User::User->new( email => $self->Email() );
        if ( !defined $userObj ) {
            $self->{Email}->setError(Common::FormObject::kErrEmailInvalid);
            $valid = 0;
        }
    } else {
        $self->{Email}->setError(Common::FormObject::kErrEmailInvalid);
        $valid = 0;
    }

    return $valid;
}

sub setPassword {
    my ($self) = @_;

    my $userObj = AppUser::DB::Item::User->Lookup( email => $self->Email() );
    return undef if ( !$userObj );

    # Before saving the new password, copy the old one to the password history
    $userObj->ArchivePassword( $userObj->user_id, $userObj->password, $userObj->last_changed );

    $userObj->date_locked( kEmptyTimestamp ); # release the lock if necessary
    $userObj->must_change(0);
    $userObj->login_attempts(0);
    $userObj->UpdatePassword( $userObj->user_id, $self->NewPassword() );
    my $now = strftime "%Y-%m-%d %H:%M:%S", localtime time;
    $userObj->last_changed($now);

    $userObj->save();
}

sub sendForgotPWEmail {
    my ($self) = @_;

    my $userObj = AppUser::DB::Item::User->Lookup( email => $self->Email() );
    return undef if ( !defined $userObj || !$userObj->user_id );

    my $recipient = $userObj->email;
    my $hostname  = RSApache::RSWebApp::GetHttpHost();

    my $tokenObj = AppUser::User::Token->new( email => $self->Email() );

    my %params            = ( Form_Email => $recipient, Form_Token => $tokenObj->GetTimedToken() );
    my $cmd               = AppUser::ForgotPW::Command::ForgotPW->new(%params);
    my $uri               = $cmd->getRedirect();
    my $forgotPasswordURL = "https://" . $hostname . $uri;

    my $to = $recipient;
    my $from = 'do-not-reply@royaltyshare.com';
    my $subject = "RoyaltyShare Password Reset";
    my $body = <<EOM;
For security reasons passwords are never saved in their original format in the RoyaltyShare system so we cannot provide you with your original password.

However, you can reset your password by going to the Reset Password page found here:

$forgotPasswordURL

From there you will be able to enter a new password for accessing your account.

Sincerely,

RoyaltyShare Support
EOM
    Common::Email->SendAWS(
        to      => $to,
        from    => $from,
        subject => $subject,
        body    => $body
    );

    return 1;
}

1;

