package AppUser::Login::Command::MFAConfig;

use strict;
use warnings;
use URI::Escape;

use lib '/app/tools/api/lib';
use API::Session;

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

# this is a special command, there's no check for session or permission
# so we'll just derive from the basic RSApache::Command base class and define
# our "app" while other "user" Commands will derive from AppUser::Command
#
use lib '/app/tools/common/lib';
use RSApache::Response::Redirect;
use RSApache::Response::XSLT;
use Common::RSApp;
use Common::MFA::Util;
use RSApache::RSWebApp;
use RSApache::Command;
use base 'RSApache::Command';

sub cmd  { return "config"; }
sub area { return "login"; }
sub app  { return "rps"; }

use constant kTemplate => '/app/tools/appuser/templates/mfa.xsl';

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

    my $form;
    my $response;
    my $redirect = uri_unescape( $self->getParam("redirect") );
    my $email    = uri_unescape( $self->getParam("email") );

    my $defaultMFAType;
    my $smsPhoneNumber;
    my $mfaVerified;
    my $useMFAType = $self->getParam("mtype"); # user's default authentication type
    my $useSMS     = $self->getParam("sms");   # set preferred MFA to SMS
    my $token      = $self->getParam("token");

    if (!$email && !$token) {
        # This could be a new portal user.
        # Let's see if we have the cookie we need.
        my $userTokenCookie = API::Session::GetUserTokenCookie();
        if ($userTokenCookie) {
            my $userToken = $userTokenCookie->value();
            my $userTokenDB = AppUser::DB::Item::UserToken->Lookup( token => $userToken );
            if ($userTokenDB) {
                $token = $userToken;
                $email = $userTokenDB->email;
            }
        }
    }

    my $user;
    if( $email ) {
        $user = AppUser::DB::Item::User->Lookup( email => $email );
        $defaultMFAType = $user->mfa_type;
        $smsPhoneNumber = $user->mfa_phone;
        $mfaVerified    = $user->mfa_verified;
        $useMFAType = $defaultMFAType if ( !$useMFAType );
    }

    my $session = RSApache::RSWebApp::GetSession();
    my $cmd     = $self->getParam("c");

    if ( $cmd && $cmd eq 'qrcode' ) {
        # Get the userID and generate the QR code; store the file URI in the XML so that the template
        # can display it.
        #
        my $user = AppUser::DB::Item::User->Lookup( email => $email );
        my $file = Common::MFA::Util->generateQRCode( user_id => $user->user_id );
        $self->{xml}{QRPath} = $file;

        my $uri = "/rps/login?c=qrcode&email=$email&token=$token";
        $self->{xml}{Redirect} = $uri;

    } elsif ( $useSMS ) {
        print STDERR "D:----- MFAConfig -- changing user preferred MFA to SMS\n";
        my $user = AppUser::DB::Item::User->Lookup( email => $email );
        $user->mfa_type( AppUser::DB::Item::User::kMFATypeSMS );
        $user->save;

        # We already have the phone number, so send a new code before redirecting
        # to the code verification screen
        Common::MFA::Util->sendSMSCode( user_id => $user->user_id );

        my $uri = "/rps/login?c=authc&email=". uri_escape($email) . "&token=$token"
            . "&mtype=" . AppUser::DB::Item::User::kMFATypeSMS;
        $uri .= "&phone=". uri_escape($smsPhoneNumber) if ( $smsPhoneNumber );

        $response = RSApache::Response::Redirect->new($uri);

    } else {
        $form = AppUser::Login::MFAConfigForm->new( redirect => $redirect );
        if ( $self->getParam('submit') ) {

            # Store the user's preferred MFA type
            #
            if ( $form->assignCGIParams( 'Form', $self->getParams() ) ) {

                my $mfaType  = $self->getParam("mfa_type");
                my $_email   = uri_escape( $form->Email() );
                my $_mfaType = ($mfaType eq 'email') ? AppUser::DB::Item::User::kMFATypeEmail :
                               ($mfaType eq 'auth' ) ? AppUser::DB::Item::User::kMFATypeAuthenticator :
                               ($mfaType eq 'sms' ) ? AppUser::DB::Item::User::kMFATypeSMS :
                               AppUser::DB::Item::User::kMFATypeNone;
                my $token    = $form->Token() || $token;

                if ( $mfaType eq 'sms' ) {
                    my $uri = "/rps/login?c=sms&email=$_email&token=$token&mtype=". AppUser::DB::Item::User::kMFATypeSMS  ;
                    $uri .= "&redirect=". uri_escape($uri);
                    $response = RSApache::Response::Redirect->new($uri);
                } elsif ( $mfaType eq 'auth' ) { # authenticator
                    my $uri = "/rps/login?c=qrcode&email=$_email&token=$token";
                    $uri .= "&redirect=". uri_escape($uri);
                    $response = RSApache::Response::Redirect->new($uri);
                } else {
                    my $uri = "/rps/login?c=auth&email=$_email&token=$token";
                    Common::MFA::Util->sendMFAPassword( email => $form->Email() );
                    $response = RSApache::Response::Redirect->new($uri);
                }

            } else {
                $form->setError(Common::FormObject::kErrFormSubmit);
                $self->addMessageXML( type => "error", code => Common::FormObject::kErrFormSubmit );
            }
        }
    }

    if ( !$response ) {
        $self->{xml}{Form} = $form;

        $self->{xml}{Email}         = uri_escape( $email );
        $self->{xml}{EmailPlain}    = $email;
        $self->{xml}{DisplayEmail} = $email;
        $self->{xml}{DefaultMFAType} = $defaultMFAType;
        $self->{xml}{SMSPhoneNumber} = $smsPhoneNumber;
        $self->{xml}{MFAVerified}    = $mfaVerified;
        $response = RSApache::Response::XSLT->new( $self->{xml}, kTemplate );
    }

    return $response;
}

1;
