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

use Apache2::Const qw(OK FORBIDDEN HTTP_OK HTTP_UNAUTHORIZED HTTP_NOT_FOUND HTTP_NOT_IMPLEMENTED);

use lib '/app/tools/common/lib';
use Common::RSApp;

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

use base 'API::Command::StatementBase';

sub area { return "client"; }
sub cmd  { return "statement"; }


sub execute {
    my $self = shift;

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

    my $runType = $self->getRouteParam(":runTypeId") || '';

    my $errorResponse = $self->_validate($runType);
    return $errorResponse if $errorResponse;

    $ENV{HOME} = '/';

    my $hClients = {};

    my $userID    = $self->{userID};                           # derived from session (see SUPER::execute)
    my $payeeType = $self->getPayeeTypeByRunType($runType);    # convert runType to payeeType

    my $portalCollection = API::DB::Item::PortalPayee->GetAllConfirmedByUserIDPayeeType($userID, $payeeType);
    while ( $portalCollection->hasNext() ) {
        my $oPortalPayee = $portalCollection->next();
        $self->_fillInClientData($runType, $hClients, $oPortalPayee);
    }

    return $self->createResponse(
        status => HTTP_OK,
        data   => {
            clients => [ @$hClients{ sort keys %$hClients } ],
        },
    );
}

sub _validate {
    my ($self, $runType) = @_;

    my $allowedRunTypes = join '|', $self->getAllowedRunTypes();

    unless ( $runType =~ /^(?:$allowedRunTypes)$/ ) {
        return $self->createResponse(
            status => HTTP_NOT_IMPLEMENTED,
            data   => { msg => "Invalid runtype" }
        );
    }

    return;
}

sub _fillInClientData {
    my ($self, $runType, $hClients, $oPortalPayee) = @_;

    my $clientID = $oPortalPayee->client_id;

    my $appSingleton = Common::RSApp->new_temporary( clientID => $clientID );
    my $dbo = Common::RSApp::GetClientDB();

    my $hClient = $self->_initClientData( $hClients, $clientID );

    if ($hClient) {
        my ($aStatements, $hasHistoricalStatements) = $self->getStatementData(
            'current', $oPortalPayee, $runType
        );
        $hClient->{has_historical} = 1 if $hasHistoricalStatements;

        # filtering statements for additional recipients
        foreach my $hStatement (@$aStatements) {
            next unless $self->_canRecipientUserSeeStatement( $oPortalPayee, $hStatement );
            $self->_addClientStatement( $hClient, $hStatement );
        }
    }

    return 1;
}

sub _initClientData {
    my ( $self, $hClients, $clientID ) = @_;

    # return data for an existing client
    return $hClients->{$clientID} if exists $hClients->{$clientID};

    my $oClient = Common::DB::Item::Client->Lookup( client_id => $clientID );

    if ($oClient) {
        return $hClients->{$clientID} = {
            client_id        => 0 + $clientID,
            client_name      => $oClient->client_name,
            display_name     => $oClient->display_name,
            email            => $oClient->email,
            has_historical   => 0,
            currentStatement => [],
        };
    }
}

sub _addClientStatement {
    my ( $self, $hClientData, $hStatementData ) = @_;

    return unless keys %$hStatementData;
    push @{ $hClientData->{currentStatement} }, $hStatementData;

    return 1;
}

sub _canRecipientUserSeeStatement {
    my ($self, $oPayee, $hStatementData) = @_;

    # it is not an additional payee statement recipient
    return 1 unless $oPayee->statement_recipient_id;

    my $dateInvited = $oPayee->date_invited;
    my $runDate     = $hStatementData->{date};
    # the recipient was invited before the run was committed or at the same time
    return 1 if $runDate ge $dateInvited;

    return 0;
}


1;
