#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------
package Raptor::Tracker::Command::SetConversionRate;
use strict;
use warnings;
use URI::Escape;

use lib '/app/tools/common/lib';
use RSApache::Response::XSLT;
use Common::Assert;
use Common::Client;

use lib '/app/tools/raptor/lib';
use Raptor::Tracker::Command::Main;

use lib '/app/tools/rps/lib';
use RPS::File::File;

use Raptor::Command;
use base 'Raptor::Tracker::Command::Base';

sub cmd  { return "currency"; }
sub area { return "tracker"; }

use constant kTemplate => '/app/tools/raptor/templates/tracker.xsl';

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

    # Give any inherited methods the first crack at this.
    # (This checks for login and basic access permissions).
    my $response = $self->SUPER::execute();
    return $response if $response;

    my $multiFilesParam    = $self->getParam('multi_files')      || 0;   # is used for multiple files processing
    my $fileParam          = $self->getParam('file')             || 0;   # fileID | [fileID1, fileID2, etc.] | 'fileID1,fileID2,etc.'
    my $currencyParam      = $self->getParam('currency')         || 0;   # MUL | 1 | float (this is weird legacy)
    my $currencyCodesParam = $self->getParam('currencyCombined') || '';  # 'USD CAD GBP etc.'
    my $currencyCode       = $self->getParam('currencyCode')     || '';

    my $aFileIDs = ref $fileParam ne 'ARRAY' ? [split(',', $fileParam)] : $fileParam;
    my $aFileObjects = $self->_getFileObjects($aFileIDs);

    # Process one file (from the main revenue page)
    if ( !$multiFilesParam ) {
        my $oFile = $aFileObjects->[0];

        # set rates
        # single currency
        if ( $currencyParam eq '1' ) {
            my $currencyUnit = $self->getParam('currencyUnit') || 0;
            $response = $self->_setCurrencyRateSingleFile($oFile, $currencyUnit, $currencyCodesParam);
        }
        # multi currencies
        elsif ($currencyParam eq 'MUL') {
            $response = $self->_setCurrencyRateSingleFile($oFile, $currencyParam, $currencyCodesParam);
        }

        return $response if $response;

        $self->{xml}{File} = $oFile->GetObjectXML( includeCurrencyList => 1 );
        $self->{xml}{File}{DateSalesFilePeriod} =
            Common::Client::Current->Locale->formatDate( $oFile->SalesFileDateBegin )
            . ' - ' .
            Common::Client::Current->Locale->formatDate( $oFile->SalesFileDateEnd );
    }
    # Process multiple files
    elsif ( $multiFilesParam ) {
        my %mapFileServiceIDs = map { $_->FileID => $_->ServiceID } @$aFileObjects;
        my $aFileIDs = [ keys %mapFileServiceIDs ];
        my $aServiceIDs = [ values %mapFileServiceIDs ];
        my $aFilesServiceNames = $self->_getFilesServiceNames( $aServiceIDs );
        my $aFilesCurrencies = $self->_getFilesUniqueCurrenciesInfo( $aFileIDs );

        # set rates
        if ( $currencyParam ) {
            $response = $self->_setCurrencyRateMultipleFiles( $aFileObjects );
            return $response if $response;
        }

        $self->{xml}{Files}{MultiFiles} = 1;
        $self->{xml}{Files}{FileIDs} = join(',', keys %mapFileServiceIDs);
        $self->{xml}{Files}{TotalFiles} = scalar keys %mapFileServiceIDs;
        $self->{xml}{Files}{ServiceNames} = $aFilesServiceNames;
        $self->{xml}{Files}{Currencies} = $aFilesCurrencies;
        $self->{xml}{Files}{SalesPeriodEndDate} = Common::Client::Current->Locale->formatDate( $aFileObjects->[0]->SalesPeriodDateEnd() );
    }

    $response = RSApache::Response::XSLT->new( $self->{xml}, kTemplate );
    return $response;
}

sub _getFileObjects {
    my ($self, $aFileIDs) = @_;

    my $aFileObjects = [];
    foreach my $fileID ( @$aFileIDs ) {
        my $oFile = RPS::File::File->new( file_id => $fileID );
        assert( $oFile );
        assert( $oFile->FileStatus != File::File::STATUS_CLOSED );

        $oFile->{ConversionInput} = 1;
        push @$aFileObjects, $oFile;
    }

    return $aFileObjects;
}

sub _setCurrencyRateSingleFile {
    my ($self, $oFile, $currencyParam, $currencyCodesParam) = @_;

    my $pageParam     = $self->getParam('page')     || 1;
    my $redirectParam = $self->getParam('redirect') || "/app/tracker?page=$pageParam";

    if ( $currencyParam ne 'MUL' ) {
        # Need to convert this value into 'normal' decimal.
        my $currencyRate = $currencyParam;
        $currencyRate = Common::Client::Current()->Locale->scrubNumber($currencyRate);
        my $result = $oFile->SetConversionRate($currencyRate);

        return RSApache::Response::Redirect->new($redirectParam) if $result;
    } else {
        my $errors = 0;
        foreach my $currencyCode ( split( ' ', $currencyCodesParam ) ) {
            my $currencyRate = $self->getParam( 'currency' . $currencyCode );
            $currencyRate = Common::Client::Current()->Locale->scrubNumber($currencyRate);
            my $result = $oFile->SetMultipleConversionRate( $currencyCode, $currencyRate );
            next if $result;

            $errors++;
        }

        return RSApache::Response::Redirect->new($redirectParam) unless $errors;
    }

    $self->addMessageXML( type => 'error', code => 'invalid_currency' );

    return;
}

sub _setCurrencyRateMultipleFiles {
    my ($self, $aFileObjects) = @_;

    my $pageParam     = $self->getParam('page')     || 1;
    my $redirectParam = $self->getParam('redirect') || "/app/tracker?c=currency_conversion_entry";
    # additional params to retain filters
    my $salesPeriodEndDateParam = $self->getParam('salesPeriodEndDate') || 0;
    my $serviceIDParam = $self->getParam('serviceID')                   || 0;
    my $conversionRateParam = $self->getParam('conversionRate')         || 0;
    my $currencyCode = $self->getParam('currencyCode')                  || '';
    my $pageSizeParam = $self->getParam('pageSize')                     || 25;

    my $aFileIDs = [ map { $_->FileID } @$aFileObjects ];
    my $hMapFileIDCurrencyRate = $self->_getFilesAssociatedCurrencies( $aFileIDs );

    my $errors = 0;
    foreach my $oFile ( @$aFileObjects ) {
        my $fileID = $oFile->FileID;
        foreach my $hEntity ( @{ $hMapFileIDCurrencyRate->{$fileID} } ) {
            my $currencyCode = $hEntity->{associated_currency};
            my $oldCurrencyRate = $hEntity->{conversion_rate};
            my $currencyRate = $self->getParam( 'currency' . $currencyCode );

            # skip if a value has not been changed
            next if sprintf('%.8f', $oldCurrencyRate) == sprintf('%.8f', $currencyRate);

            $currencyRate = Common::Client::Current()->Locale->scrubNumber($currencyRate);
            my $result = $oFile->SetMultipleConversionRate( $currencyCode, $currencyRate );
            next if $result;

            $errors++;
        }
    }

    unless ($errors) {
        $redirectParam .= "&page=$pageParam";
        $redirectParam .= "&msg=success|rates_entered";
        $redirectParam .= "&files_num=" . scalar(@$aFileObjects);

        return RSApache::Response::Redirect->new($redirectParam);
    }

    $self->addMessageXML( type => 'error', code => 'invalid_currency' );

    return;
}

sub _getFilesUniqueCurrenciesInfo {
    my ($self, $aFileIDs) = @_;

    my $filePlaceholders = join(', ', map {'?'} @$aFileIDs);
    my $sql = qq/
        SELECT
            ROUND(SUM(revenue), 2) AS SumNativeRevenue,
            ROUND(AVG(CASE WHEN conversion_rate <> 0 THEN conversion_rate END), 8) AS Rate,
            ROUND(1 \/ IFNULL(AVG(CASE WHEN conversion_rate <> 0 THEN conversion_rate END), 1), 8) AS ReverseRate,
            ROUND(SUM(revenue) * IFNULL(AVG(CASE WHEN conversion_rate <> 0 THEN conversion_rate END), 1), 2) AS SumPrettyRevenue,
            associated_currency AS CurrencyCode
        FROM user_input_conversion_rate
        WHERE file_id IN ($filePlaceholders)
        GROUP BY associated_currency
        ORDER BY associated_currency;
    /;

    my $db = Common::RSApp::GetClientDB();
    my $sth = $db->DoCmdWithPlaceholders($sql, [@$aFileIDs]);
    my $aData = $sth->fetchall_arrayref({});

    foreach my $hRow ( @$aData ) {
        $hRow->{'CurrencySymbol'} = Common::CurrencyFormat::Symbol( $hRow->{CurrencyCode} );
    }

    return $aData;
}

sub _getFilesAssociatedCurrencies {
    my ($self, $aFileIDs) = @_;

    my $filePlaceholders = join(', ', map {'?'} @$aFileIDs);
    my $sql = qq/
        SELECT
            file_id,
            conversion_rate,
            associated_currency
        FROM user_input_conversion_rate
        WHERE file_id IN ($filePlaceholders)
        ORDER BY file_id
    /;

    my $db = Common::RSApp::GetClientDB();
    my $sth = $db->DoCmdWithPlaceholders($sql, [@$aFileIDs]);
    my $aData = $sth->fetchall_arrayref({});

    my $hData = {};
    foreach my $hRow ( @$aData ) {
        # push @{ $hData->{ $hRow->{file_id} } }, $hRow->{associated_currency};
        push @{ $hData->{ $hRow->{file_id} } }, {
            conversion_rate => $hRow->{conversion_rate},
            associated_currency => $hRow->{associated_currency},
        }
    }

    return $hData;
}

sub _getFilesServiceNames {
    my ($self, $aServiceIDs) = @_;

    my $servicePlaceholders = join(', ', map {'?'} @$aServiceIDs);
    my $sql = qq/
        SELECT
            service_name AS ServiceName
        FROM service
        WHERE service_id IN ($servicePlaceholders)
        GROUP BY service_name
        ORDER BY service_name
    /;

    my $db = Common::RSApp::GetClientDB();
    my $sth = $db->DoCmdWithPlaceholders($sql, [@$aServiceIDs]);
    my $aData = $sth->fetchall_arrayref();

    @$aData = map { $_->[0] } @$aData;

    return $aData;
}


1;
