package AppUser::Login::MFAAuthForm;
use strict;
use warnings;

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

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

use Common::FormObject;
use base 'Common::FormObject';

use constant kMaxMFAPasswordAge   => 180; # 180 seconds (3 minutes)

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

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

    my $email;
    my $mfaType;
    my $masterUserID = Common::RSApp::GetMasterUserID();
    if ($masterUserID) {
        my $user = AppUser::DB::Item::User->Lookup( user_id => $masterUserID );
        if ( defined $user ) {
            $email   = $user->email;
            $mfaType = $user->mfa_type;
        }
    }

    $self->{Email}    = Common::FormObject::Scalar::EmailAddress->new( value => $email, required => 1 );
    $self->{MFAType}  = Common::FormObject::Scalar::String->new( value => $mfaType );
    $self->{Token}    = Common::FormObject::Scalar::String->new( required => 1 );
    $self->{Password} = Common::FormObject::Scalar::String->new( required => 1 );
    $self->{Redirect} = Common::FormObject::Scalar::String->new( value    => $args{redirect} );

    return $self;
}

# validate the user's 2FA
sub validate {
    my ($self) = @_;

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

    # Our base class will validate that the password is a valid string.
    # We'll then do a second level of validation here.
    #
    if ($valid) {

        # is this the email from an existing user?
        #
        my $userObj = AppUser::DB::Item::User->Lookup( email => $self->Email() );
        if ( defined $userObj && $userObj->user_id ) {

            my $userData = $userObj->GetLoginData( $userObj->user_id );

            if ( $self->MFAType() == AppUser::DB::Item::User::kMFATypeEmail ) {
print STDERR "D:---- MFAAuthForm - validating email code...\n"; # XXX

                if ( $userObj->mfa_password eq $self->Password() ) {

                    if( $userData->{mfa_password_age} > kMaxMFAPasswordAge ) {
                        $self->{Password}->setError(Common::FormObject::kErrPasswordInvalid); 
                        $valid = 0;
                    } else {
                        $valid = 1;
                    }
                    $userObj->mfa_password('');
                    $userObj->mfa_date_created('0000-00-00 00:00:00');
                    $userObj->save;

                } else {
                    $self->{Password}->setError(Common::FormObject::kErrPasswordInvalid); 
                    $valid = 0;
                }

            } elsif( $userObj->mfa_type == AppUser::DB::Item::User::kMFATypeAuthenticator ) {
print STDERR "D:---- MFAAuthForm - validating authenticator code...\n"; # XXX

                if( Common::MFA::Util->isValidAuthenticatorCode( code => $self->Password(), user_id => $userObj->user_id) ) {
                    $valid = 1;
                } else {
                    $self->{Password}->setError(Common::FormObject::kErrPasswordInvalid); 
                    $valid = 0;
                }

            } elsif( $userObj->mfa_type == AppUser::DB::Item::User::kMFATypeSMS ) {
print STDERR "D:---- MFAAuthForm - validating SMS code...\n"; # XXX

                if( Common::MFA::Util->isValidSMSCode( code => $self->Password(), user_id => $userObj->user_id) ||
                    ( ! Common::RSApp::IsProductionServer() && $self->Password() eq '999999' ) ) {
                    $valid = 1;
                } else {
                    $self->{Password}->setError(Common::FormObject::kErrPasswordInvalid);
                    $valid = 0;
                }
            }

        } else {
print STDERR "D:---- MFAAuthForm - user not found; invalid email ". $self->Email() . " !!!\n"; # XXX
            $self->{Email}->setError(Common::FormObject::kErrEmailNotFound);
            $valid = 0;
        }
    } else { #
print STDERR "D:---- MFAAuthForm - parent validate failed !!!\n"; # XXX
    }

    return $valid;
}

1;
