#!/usr/bin/perl
#------------------------------------------------------------ 
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
# $Id$
#------------------------------------------------------------ 
use strict;

use Data::Dumper;
use Getopt::Std;
use POSIX qw(ceil);
use Carp;

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

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

use lib '/app/tools/rps/lib';
use RPS::Statement::Mechanical::PDF;
use RPS::DB::Item::MechanicalRun;
use RPS::DB::Item::MechanicalStatement;
use RPS::DB::Item::MechanicalStatementItem;
use RPS::DB::Item::MechanicalStatementTrack;
use RPS::DB::Item::MechanicalStatementLicense;
use RPS::DB::Item::TrackLicense;
use RPS::DB::Item::LicenseReserve;
use RPS::DB::Item::LicenseReserveRun;
use RPS::DB::Item::MechanicalStatementAdjustmentItem;
use RPS::DB::Item::SaleRunMap;
#use RPS::DB::Item::SaleMechanicalStatementItemMap;
use RPS::DB::Item::MechanicalRunCarryover;

my $gVerbosityLevel = 1;

# Get the id from the command-line
#
my %options;
_parseCommandLine(\%options);
_deleteRun($options{clientID}, $options{runID});



sub _parseCommandLine
{
    my ($settings) = @_;

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

    if (! $opt{r} || ! $opt{c})
    {
        _usage();
        exit(1);
    }
    $settings->{runID} = $opt{r};
    $settings->{clientID} = $opt{c};
    if ($opt{V})
    {
        $gVerbosityLevel = $opt{V};
    }
}

sub _usage
{
    print "\nusage: $0 -c client_id -r run_id\n";
    print "\n";
    print "Arguments:\n";
    print "\t-c <client_id>\t\tThe client_id of the client to process\n";
    print "\t-r <run_id>\t\tThe mechanical_run_id of the mechanical royalty run to delete\n";
}


sub _deleteRun
{
    my ($clientID, $runID) = @_;
    assert($clientID);
    assert($runID);

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


    # Get all of the statements created by this run,
    # and delete them.
    #
    my $statements = RPS::DB::Item::MechanicalStatement->GetByMechanicalRunID($runID);

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

    _deleteOrphanedReserves();
    RPS::DB::Item::LicenseReserveRun->DeleteByMechanicalRunID($runID);


    # Delete entries in the mechanical_run_carryover table.
    #
    RPS::DB::Item::MechanicalRunCarryover->DeleteByMechanicalRunID($runID);


    # Delete from the SaleRunMap table
    #
    RPS::DB::Item::SaleRunMap->DeleteByMechanicalRunID($runID);


    # Get rid of any PDF statements.
    #
    my $pdfPath = RPS::Statement::Mechanical::PDF::StatementPathFromRunID($runID);
    if (-d $pdfPath)
    {
        system("rm -rf $pdfPath");
    }

    # Delete this run from the mechanical_run table.
    #
    _report("deleting from mechanical run table");
    my $run = RPS::DB::Item::MechanicalRun->Lookup(mechanical_run_id => $runID);
    $run->delete();
}




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

    my $statementID = $statement->mechanical_statement_id;


    # We can't delete statements that have been committed already - it's too late, accounts have already
    # been modified.
    #
    if (RPS::DB::Item::MechanicalStatement::kStatusAccepted == $statement->status)
    {
        die "Error - Cannot delete a committed statement!";
    }

    _report("deleting statement $statementID");
    $statement->delete();


    # Get rid of the sale/statement_item map entries
    #
    my $statementItems = RPS::DB::Item::MechanicalStatementItem->GetByMechanicalStatementID($statementID);
    while ($statementItems->hasNext())
    {
        my $item = $statementItems->next();
        my $id = $item->mechanical_statement_item_id;

        # I am going to need to set the status of these sales back to kUnprocessed...
        # !!! This doesn't seem like such a hot idea, since status can span multiple runs.
        # !!! I am instead just going to leave the status alone.
        # !!! The only status that _really_ matters is the kComplete status, which will only
        # !!! be set on a sale that has been both accepted, and has no unallocated shares.
        #
#        my $mapItems = RPS::DB::Item::SaleMechanicalStatementItemMap::GetByMechanicalStatementItemID($id);
#        while ($mapItems->hasNext())
#        {
#            my $item = $mapItems->next();
#            my $saleID = $item->sale_id;
#
#            my $sale = Raptor::DB::Item::Sale->Lookup(sale_id => $saleID);
#            $sale->mechanical_royalty_status(Raptor::DB::Item::Sale::kUnprocessed);
#            $sale->save();
#        }
#

        # !!! I don't think I can delete these inline?  Maybe I should try.
        #
#        _report("  ... deleting sale map entries",2);
#        RPS::DB::Item::SaleMechanicalStatementItemMap->DeleteByMechanicalStatementItemID($id);

        $item->delete();
    }

    _report("  ... deleting statement track items",2);
    RPS::DB::Item::MechanicalStatementTrack->DeleteByMechanicalStatementID($statementID);

    _report("  ... deleting statement license items",2);
    RPS::DB::Item::MechanicalStatementLicense->DeleteByMechanicalStatementID($statementID);

    _report("  ... deleting statement adjustment items",2);
    RPS::DB::Item::MechanicalStatementAdjustmentItem->DeleteByMechanicalStatementID($statementID);

    _report("  ... deleting statement items",2);
    RPS::DB::Item::MechanicalStatementItem->DeleteByMechanicalStatementID($statementID);

}


sub _deleteOrphanedReserves
{
    # Grab _all_ the license reserves, then look for 'orphaned' reserves.
    #
    _report("  ... deleting orphaned license reserves",2);
    my $all = RPS::DB::Item::LicenseReserve->GetAll();
    while (my $reserve = $all->next())
    {
        my $id = $reserve->original_statement_item_id;
        next unless ($id);
        my $statementItem = RPS::DB::Item::MechanicalStatementItem->Lookup(mechanical_statement_item_id => $id);
        if (! $statementItem)
        {
            # This reserve is bogus - kill it.
            #
            $reserve->delete();
        }
    }
}


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

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

