package API::Command::Confirm;
use strict;
use warnings;

use Data::Dumper;
use Apache2::Const qw(OK FORBIDDEN HTTP_OK HTTP_UNAUTHORIZED HTTP_NOT_IMPLEMENTED);
use CGI::Cookie;
use POSIX (qw/strftime/);

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

use lib '/app/tools/api/lib';
use API::Response;
use API::DB::Item::PortalInvite;
use API::DB::Item::PortalPayee;
use API::Util;

use base 'API::Command';

sub area { return "user"; }
sub cmd  { return "confirm"; }

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

    if ( $self->getCGI->request_method ne 'POST' ) {
        return $self->createResponse(
            status => HTTP_UNAUTHORIZED,
            data   => { msg => "Invalid request method" }
        );
    }

    my $inviteKey = $self->getRouteParam(":inviteKey");

    my $username  = $self->getInputParam("username");
    my $password  = $self->getInputParam("password");
    my $firstName = $self->getInputParam("firstname");
    my $lastName  = $self->getInputParam("lastname");


    my $oInvite = API::DB::Item::PortalInvite->Lookup( invite_key => $inviteKey );
    if ( !$oInvite ) {
        return $self->createResponse(
            status => HTTP_UNAUTHORIZED,
            data   => { msg => "Invalid invite" }
        );
    }

    if ( $oInvite->date_confirmed && '0000-00-00 00:00:00' ne $oInvite->date_confirmed ) {
        return $self->createResponse(
            status => HTTP_UNAUTHORIZED,
            data   => { msg => "Invite already confirmed" }
        );

    }

    if ( !$self->isSupportedPayeeType( $oInvite->payee_type ) ) {
        return $self->createResponse(
            status => HTTP_NOT_IMPLEMENTED,
            data   => { msg => "Unsupported payee type " . $oInvite->payee_type }
        );
    }

    # Use the username from the invite, not what was passed in
    $username = $oInvite->invitee;
    unless ( $username ) {
        die("API::Command::Confirm - detected invite without an email");
    }

    # If this user already has an ID, we need to pass it back to the frontend.
    my $userID;
    my $ok2confirm = 0;

    # Check if the portal user exists
    my $oUser = AppUser::DB::Item::User->Lookup( email => $username );
    if ( $oUser ) {
        $userID = $oUser->user_id;

        # If this a pre-existing RPS user (user_type=0), then we'll update it
        # to a portal-eligible user.  We'll also auto-confirm the portal user
        # when we create the portal_payee entry below (ok2confirm=1).
        if ( $oUser->user_type == AppUser::DB::Item::User::kUserTypeNormal ) {
            $oUser->user_type( AppUser::DB::Item::User::kUserTypePortal );
            $oUser->save;
            $ok2confirm = 1;
        }
    }
    else {
        # create a new RSCOMMON.user
        if ( '' eq $password ) {
            return $self->createResponse(
                status => HTTP_UNAUTHORIZED,
                data   => { msg => "Password required for new user" }
            );
        }

        my ( $st, $emsg ) = API::Util->validatePassword($password);
        if ( $st != 200 ) {
            return $self->createResponse(
                status => $st,
                data   => { msg => API::Util::kInvalidPassword, emsg => $emsg }
            );
        }

        my %args = (
            'email'     => $username,
            'password'  => AppUser::DB::Item::User->HashPassword($password),
            'user_type' => AppUser::DB::Item::User::kUserTypePortal
        );
        $args{first_name} = $firstName if ( '' ne $firstName );
        $args{last_name}  = $lastName  if ( '' ne $lastName );
        $args{last_changed} = strftime "%Y-%m-%d %H:%M:%S", localtime time;

        $oUser = AppUser::DB::Item::User->Create(%args);
        $oUser->save();

        $ok2confirm = 1;
    }

    # Add portal payee user
    my %args = (
        'user_id'                => $oUser->user_id,
        'invite_key'             => $inviteKey,
        'client_id'              => $oInvite->client_id,
        'payee_id'               => $oInvite->payee_id,
        'statement_recipient_id' => $oInvite->statement_recipient_id,
        'payee_type'             => $oInvite->payee_type,
        'date_invited'           => $oInvite->date_invited,
        'invitee'                => $username
    );
    my $currentTime = Common::Util::today_and_now();

    # We auto-confirm the 1st time the portal user is associated with a client,
    # otherwise the user will have to manually confirm the user/client relation.
    $args{date_confirmed} = $currentTime if $ok2confirm;

    my $p = API::DB::Item::PortalPayee->Create(%args);
    $p->save();

    # Expire the invites
    $oInvite->date_confirmed($currentTime);
    $oInvite->save();

    # Update the payee if we're auto-confirming
    $self->_updatePayeeOrRecipientConfirmationDate($oInvite, $currentTime) if $ok2confirm;

    if ($userID) {
        return $self->createResponse(
            status => HTTP_OK,
            data   => {
                user_id => $userID,
                msg     => "Portal user successfully registered"
            }
        );
    }

    return $self->createResponse(
        status => HTTP_OK,
        data   => { msg => "Portal user successfully registered" }
    );
}

sub _updatePayeeOrRecipientConfirmationDate {
    my ($self, $oInvite, $currentTime) = @_;

    my $clientID    = $oInvite->client_id;
    my $payeeID     = $oInvite->payee_id;
    my $payeeType   = $oInvite->payee_type;
    my $recipientID = $oInvite->statement_recipient_id;

    my $appSingleton = Common::RSApp->new_temporary( clientID => $oInvite->client_id );
    my $oPayee = $self->getPayeeOrRecipientByType( $payeeType, $payeeID, $recipientID );

    die( __PACKAGE__ . " - unable to find clientID: $clientID, PayeeID: $payeeID, PayeeType: $payeeType, RecipientID: $recipientID" )
        unless $oPayee;

    $oPayee->date_confirmed($currentTime);
    $oPayee->save();

    return 1;
}




1;
