#!/usr/bin/perl
use strict;


use Data::Dumper;
use Getopt::Std;
use POSIX qw(ceil);
use POSIX ":sys_wait_h";
use Sys::Hostname;
use Carp;


use lib '/app/tools/common/lib';
use Common::DB::Item;
use Common::Assert;
use Common::TextProgressBar;
use Common::Timer;
use Common::DB::Item::Service;
use Common::RSMath;

#use lib '/app/tools/data_classes/lib';
#use File::Sale;
use lib '/app/tools/raptor/lib';
#use Raptor::Sale::Sale;
use Raptor::DB::Item::Sale;
use Raptor::DB::Item::File;

use lib '/app/tools/rps/lib';
use RPS::Mechanical::MechanicalRun;
use RPS::DB::Item::MechanicalRun;
use RPS::DB::Item::Product;
use RPS::DB::Item::Publisher;
use RPS::DB::Item::PublisherAccount;
use RPS::DB::Item::Track;
use RPS::DB::Item::TrackLicense;
use RPS::DB::Item::LicenseReserve;
use RPS::DB::Item::LicenseReserveRun;
use RPS::DB::Item::ReserveLiquidation;
use RPS::DB::Item::PendingTransaction;
use RPS::DB::Item::MechanicalStatement;
use RPS::DB::Item::MechanicalStatementTransaction;
use RPS::DB::Item::MechanicalStatementItem;
use RPS::DB::Item::MechanicalCarryover;
use RPS::DB::Item::MechanicalStatementLicense;
use RPS::DB::Item::SaleMechanicalStatementItemMap;
use RPS::DB::Item::FinanceAccount;
use RPS::DB::Item::FinanceTransaction;

my $gVerbosityLevel = 1;



# Parse the command-line options.
#
my %options;
_parseCommandLine(\%options);


# Instantiate the application singleton object.
#
my $appSingleton = Common::RSApp->new(clientID => 31);

my $db = Common::RSApp::GetClientDB();

# Get all the statements from run 44
#
my $statements = RPS::DB::Item::MechanicalStatement::GetByMechanicalRunID(44);

while ($statements->hasNext())
{
    my $statement = $statements->next();
    _fixIt($statement);
}


sub _fixIt
{
    my ($statement) = @_;

    # get the statement total.
    my $statementID = $statement->mechanical_statement_id;


    # !!! This is going to have to change.
    #
    # We no longer assume the new balance, or applied to balance.
    #
    # Instead...  we first apply the statement subtotal as a credit,
    # then apply each pending transaction.
    #

    my $publisherID = $statement->publisher_id;
    my $payorID = $statement->payor_id;

    # Create a new publisher_id/payor_id/account_id mapping if necessary
    #
    my $accountMap = RPS::DB::Item::PublisherAccount->Lookup(publisher_id => $publisherID, payor_id => $payorID);
    if (! $accountMap)
    {
        $accountMap = RPS::DB::Item::PublisherAccount->Create
        (
            publisher_id => $publisherID,
            payor_id => $payorID,
        );
        $accountMap->save();
    }


    # Create a new finance account if necessary
    #
    my $accountID = $accountMap->finance_account_id;
    if (! $accountID)
    {
        # Create a new account 
        #
        my $account = RPS::DB::Item::FinanceAccount->Create
        (
            description => "holdover account for publisher $publisherID payor $payorID",
            type_code => RPS::DB::Item::FinanceAccount::kAccountTypeHoldover,
        );
        $account->save();
        $accountID = $account->finance_account_id;


        # save the account_id in the map table
        #
        $accountMap->finance_account_id($accountID);
        $accountMap->save();
    }


    # Apply the statement subtotal as a transaction to this account.
    #
    # !!! Unlike commit_mechanicals, we only do this when there is an amount_due
    # !!! We want the memo to be the run name - I'd like a consistent interface around that.
    my $amountDue = $statement->amount_due;
    if ($amountDue > 0)
    {
        my $transaction = RPS::DB::Item::FinanceTransaction->Create
        (
            finance_account_id => $accountID,
            amount => $amountDue,
            type_code => RPS::DB::Item::FinanceTransaction::kTypeClosingBalance,
            memo => "mechanical statement $statementID royalties owed",
        );
        $transaction->save();
    }

}



sub _usage
{
    print "\nusage: $0 -c client_id [-V]\n";
    print "\n";
    print "Arguments:\n";
    print "\t-c <client_id>\t\tThe client_id of the client to process\n";
    print "\t-V <N>\t\t\tVerbosity level - 0 means no output\n";
}


sub _report
{
    my ($string, $verbosity) = @_;
    $verbosity = 1 unless defined $verbosity;

    if ($gVerbosityLevel >= $verbosity)
    {
        print $string . "\n";
    }
}


# Pass dates in 'yyyy-mm-dd' format.
#
sub _parseCommandLine
{
    my ($settings) = @_;

    my %opt;
    getopts('V:', \%opt);

    if (defined $opt{V})
    {
        $gVerbosityLevel = $opt{V};
    }
}

