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

use Data::Dumper;
use Apache2::Const qw(HTTP_FORBIDDEN HTTP_OK HTTP_UNAUTHORIZED HTTP_NOT_FOUND HTTP_NOT_IMPLEMENTED);
use CGI::Cookie;

use lib '/app/tools/common/lib';
use Common::Util;
use AppUser::DB::Item::User;
use Common::DB::Item::PayeeType;

use lib '/app/tools/rps/lib';
use RPS::DB::Item::ArtistPayee;
use RPS::DB::Item::ArtistPayeeStatementRecipient;
use RPS::Portal::Token;

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

use base 'API::Command';

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

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

    my $response = $self->SUPER::execute();
    return $response if $response;

    my $clientID    = $self->getInputParam("client_id")    || 0;
    my $payeeID     = $self->getInputParam("payee_id")     || 0;
    my $payeeType   = $self->getInputParam("payee_type")   || 0;
    my $recipientID = $self->getInputParam("recipient_id") || 0;

    # We're using the user id from the session, so it's safe to assume that user exists.
    my $oUser = AppUser::DB::Item::User->Lookup(
        user_id   => $self->{userID},
        user_type => AppUser::DB::Item::User::kUserTypePortal
    );

    my $oInvite;
    my $invites = API::DB::Item::PortalInvite->GetLatestInvite(
        client_id              => $clientID,
        payee_id               => $payeeID,
        payee_type             => $payeeType,
        statement_recipient_id => $recipientID
    );

    # There only be one invite returned from the query.
    while ( $invites->hasNext() ) {
        $oInvite = $invites->next();
    }

    my $errorResponse = $self->_validate(
        $oUser, $oInvite, $clientID, $payeeID, $payeeType, $recipientID
    );
    return $errorResponse if $errorResponse;

    my $currentTime = Common::Util::today_and_now();
    $self->_createOrUpdatePortalUser($oUser, $oInvite, $currentTime);
    $self->_confirmInvite($oInvite, $currentTime);
    $self->_updatePayee($oInvite, $currentTime);

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

sub _validate {
    my ($self, $oUser, $oInvite, $clientID, $payeeID, $payeeType, $recipientID) = @_;

    unless ( $oInvite ) {
        Common::Log::Print(
            "No invite found for clientID($clientID) "
            . "payeeID($payeeID) payeeType($payeeType) recipientID($recipientID)"
        );
        return $self->createResponse(
            status => HTTP_UNAUTHORIZED,
            data   => { msg => "Invite not found" }
        );
    }

    # Check to see if the invitation email address matches the user's email address.
    if ( lc($oUser->email) ne lc($oInvite->invitee) ) {
        Common::Log::Print(
            "User email does not match payee email". $oInvite->invitee
        );
        return $self->createResponse(
            status => HTTP_UNAUTHORIZED,
            data   => { msg => "Invite is invalid" }
        );
    }

    # Check to see if the invite has already been confirmed.
    if ( $oInvite->date_confirmed && '0000-00-00 00:00:00' ne $oInvite->date_confirmed ) {
        Common::Log::Print(
            "Invite already confirmed on ". $oInvite->date_confirmed
        );
        return $self->createResponse(
            status => HTTP_UNAUTHORIZED,
            data   => { msg => "Invite already confirmed" }
        );
    }

    # Check for supported payee type(s)
    if ( !$self->isSupportedPayeeType( $oInvite->payee_type ) ) {
        Common::Log::Print(
            "Unsupported payee type ". $oInvite->payee_type
        );
        return $self->createResponse(
            status => HTTP_NOT_IMPLEMENTED,
            data   => { msg => "Unsupported payee type " . $oInvite->payee_type }
        );
    }

    return;
}

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

    my $oPortalUser = API::DB::Item::PortalPayee->Lookup( invite_key => $oInvite->invite_key );

    if ( $oPortalUser ) {
        $oPortalUser->date_confirmed($currentTime);
    } else {
        my %args = (
            user_id                => $oUser->user_id,
            invite_key             => $oInvite->invite_key,
            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                => $oInvite->invitee,
            date_confirmed         => $currentTime
        );
        $oPortalUser = API::DB::Item::PortalPayee->Create(%args);
    }

    $oPortalUser->save();

    return 1;
}

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

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

    return 1;
}

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

    my $appSingleton = Common::RSApp->new_temporary( clientID => $oInvite->client_id );

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

    my $oPayee = $self->getPayeeOrRecipientByType($payeeType, $payeeID, $recipientID);

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

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

    return 1;
}


1;
