#!/usr/bin/perl

use strict;
use warnings;
use open ':std', ':encoding(UTF-8)';

use JSON::XS;
use FileHandle;
use Math::Round;
use DateTime::Format::DateParse;
use Text::CSV::Easy(qw/csv_build csv_parse/);

use lib '/var/app/orchard/collab/jgetter/perllib';
use Orchard::Session;

my $dbh = Orchard::Session::getdbh('orchdev');
my $dbx = Orchard::Session::getdbx('royqa');

my $file = '12periodsRunController2686.csv';

logMessage( 'info', "$file ..." );

my $summ;
my $href;

my $infile = FileHandle->new( $file, 'r' );
while (<$infile>) {
    chomp;
    my ( $pid, $contract, $cur, $period, $type, $origcurr ) = csv_parse($_);

    # next if $pid != 27990;
    my $amount = sprintf( "%.2f", $origcurr );
    $href->{$pid}->{$period}->{$type} = $amount;
    $href->{$pid}->{$period}->{'currency'} = $cur;

    $summ->{$period}->{$pid}->{$type} = $amount;
    $summ->{$period}->{$pid}->{'contract_id'} = $contract;
}
$infile->close;

my $ledger;
foreach my $pid ( sort { $a <=> $b } keys %{$href} ) {
    my $openbal = 0;
    foreach my $period ( sort { $a <=> $b } keys %{ $href->{$pid} } ) {
        my $data = $href->{$pid}->{$period};
        ## revenue
        my $rev = $data->{'dig_net_receipt'};
        if ( defined $rev ) {
            push @{ $ledger->{$period}->{$pid} },
              {
                'payee_id'         => $pid + 1_000_000,
                'ledger_type'      => $rev < 0 ? 'debit' : 'credit',
                'currency_code'    => $data->{'currency'},
                'currency_amount'  => $rev,
                'previous_balance' => $openbal,
                'current_balance'  => $rev + $openbal,
                'note'             => "$period dig_net_receipt"
              };
            $openbal = $rev + $openbal;
        }

        # adj
        my $adj = $data->{'manual_adjustment'};
        if ( defined $adj ) {
            push @{ $ledger->{$period}->{$pid} },
              {
                'payee_id'         => $pid + 1_000_000,
                'ledger_type'      => $adj < 0 ? 'debit' : 'credit',
                'currency_code'    => $data->{'currency'},
                'currency_amount'  => $adj,
                'previous_balance' => $openbal,
                'current_balance'  => $adj + $openbal,
                'note'             => "$period manual_adjustment"
              };
            $openbal = $adj + $openbal;
        }
    }
}

eval {

    my $rsfile = FileHandle->new( 'runSummary.csv',  'w' );
    my $lpfile = FileHandle->new( 'ledgerPayee.csv', 'w' );

    my $payee_count = scalar keys %{$href};

    foreach my $row ( @{ $dbh->selectall_arrayref('SELECT * FROM period WHERE period_id BETWEEN 244 AND 255') } ) {
        my ( $pid, $y, $q, $m, $status ) = @{$row};

        my $dt = DateTime::Format::DateParse->parse_datetime("$y-$m-1");

        ## close date lastday of month
        my $dt2 = $dt->clone;
        my $dt3 = $dt->clone;
        $dt2->add( months => 1 )->subtract( days => 1 );
        $dt3->add( days   => 18 );

        ## accounting period
        logMessage( 'info', "Create/find accounting period for $pid" );
        my $acct_period = $dbx->resultset('RoyaltyAccounting::AccountingPeriod')->find_or_create( {
                'accounting_period_id' => $pid,
                'name'                 => $dt->month_name . " " . $dt->year . " Legacy Run",
                'status'               => 'Closed',
                'closed_date'          => $dt2->ymd('-'),
                'created_by'           => 2076,
                'created_at'           => $dt->ymd('-'),
                'last_modified_by'     => 2076,
                'last_modified'        => Orchard::Session::mysql_now()
            },
            { 'key' => 'uidx_acct_period_name' }
        );

        ## accounting run
        logMessage( 'info', "Create/find accounting run for $pid / 2686" );
        my $acct_run = $dbx->resultset('RoyaltyAccounting::AccountingRun')->search( {
                'accounting_period_id' => $acct_period->accounting_period_id,
                'run_controller_id'    => 2686
            }
        )->first;
        if ( not defined $acct_run ) {
            $acct_run = $dbx->resultset('RoyaltyAccounting::AccountingRun')->create( {
                    'accounting_period_id' => $acct_period->accounting_period_id,
                    'run_controller_id'    => 2686,
                    'run_status'           => 'Committed',
                    'start_date'           => $dt3->ymd('-'),
                    'payee_count'          => $payee_count,
                    'summary_export_url'   => "Period $pid import from vendor_accounting",
                    'created_by'           => 2076,
                    'created_at'           => $dt3->ymd('-'),
                    'last_modified_by'     => 2076,
                    'last_modified'        => Orchard::Session::mysql_now()
                }
            );
        }

        ## create royalty ledger_event
        logMessage( 'info', "Create/find revenue event run for target 2686 commit_royalty" );
        my $rev_event = $dbx->resultset('RoyaltyAccounting::LedgerEvent')->search( {
                'target_type' => 'accounting_run',
                'target_id'   => $acct_run->accounting_run_id,
                'event_name'  => 'commit_royalty'
            }
        )->first;
        if ( not defined $rev_event ) {
            $rev_event = $dbx->resultset('RoyaltyAccounting::LedgerEvent')->create( {
                    'target_type' => 'accounting_run',
                    'target_id'   => $acct_run->accounting_run_id,
                    'event_name'  => 'commit_royalty',
                    'event_date'  => Orchard::Session::mysql_now()
                }
            );
        }
        ## create adjustment ledger_event
        logMessage( 'info', "Create/find revenue event run for target 2686 commit_adjustment" );
        my $adj_event = $dbx->resultset('RoyaltyAccounting::LedgerEvent')->search( {
                'target_type' => 'accounting_run',
                'target_id'   => $acct_run->accounting_run_id,
                'event_name'  => 'commit_adjustment'
            }
        )->first;
        if ( not defined $adj_event ) {
            $adj_event = $dbx->resultset('RoyaltyAccounting::LedgerEvent')->create( {
                    'target_type' => 'accounting_run',
                    'target_id'   => $acct_run->accounting_run_id,
                    'event_name'  => 'commit_adjustment',
                    'event_date'  => Orchard::Session::mysql_now()
                }
            );
        }

        ## run summary item and ledger
        foreach my $payee ( sort { $a <=> $b } keys %{ $summ->{$pid} } ) {
            my $data = $summ->{$pid}->{$payee};

            my $rsline = csv_build( (
                    $acct_run->accounting_run_id, $data->{'contract_id'}, $data->{'dig_net_receipt'},
                    $data->{'manual_adjustment'}, Orchard::Session::mysql_now()
                )
            );
            $rsfile->print("\\N,$rsline\n");

            ## ledger entries
            logMessage( 'info', "Create/find ledger items for payee: $payee period: $pid" );
            my $ledger_entries = $ledger->{$pid}->{$payee};
            if ( defined $ledger_entries ) {
                foreach my $le ( @{$ledger_entries} ) {
                    if ( $le->{'note'} =~ m/.*adjustment/ ) {
                        $le->{'ledger_event_id'} = $adj_event->ledger_event_id;
                    } else {
                        $le->{'ledger_event_id'} = $rev_event->ledger_event_id;
                    }
                    my $lpline = csv_build( (
                            $le->{'payee_id'},        $le->{'ledger_event_id'},
                            $le->{'ledger_type'},     $le->{'currency_code'},
                            $le->{'currency_amount'}, $le->{'previous_balance'},
                            $le->{'current_balance'}, $le->{'note'},
                            1952,                     $dt2->ymd('-'),
                            1952,                     Orchard::Session::mysql_now()
                        )
                    );
                    $lpfile->print("\\N,$lpline\n");
                }
            }
        }
    }
};
if ($@) {
    my $err;
}
