use strict;
use lib '/app/tools/common/lib';
use lib '/app/tools/raptor/lib';
use lib '/app/tools/rps/lib';

use Common::RSApp;
use Common::Client;
use Common::Log;
use Raptor::DB::Item::Sale;
use Raptor::DB::Item::File;
use RPS::Sale::Match;
use RPS::File::Sale;



my $clientID = $ARGV[0];
my $app = Common::RSApp->new(clientID => $clientID);
my $client = Common::Client::Current();

Common::Log::Print("running for client $clientID: " . $client->ClientName());


# Step one:  Find bad sales.
my $badSales = Raptor::DB::Item::Sale->GetAll("SELECT * FROM sale WHERE product_id > 0 AND product_id NOT IN (select product_id from product)");
my $badCount = $badSales->size();
my $count = 0;

my $matchCount = 0;
my $matcher = RPS::Sale::Match->new(client_id => $clientID);

my %badFileSale;

my $unitSum;
my $revenueSum;

while (my $sale = $badSales->next())
{
	$count++;
	if (0 == $count % 1000)
	{
		Common::Log::Print("$count / $badCount");
	}


	# Let's try and re-match this sale.
	#
	my $file = Raptor::DB::Item::File->Lookup(file_id => $sale->file_id());
	my $fileServiceID = $file->service_id();
	my $matchData = {
		service_id 			=> $fileServiceID,
		media_type 			=> $sale->media_type(),
		album				=> $sale->album_name(),
		artist				=> $sale->artist_name(),
		client_product_id	=> $sale->client_product_id(),
		format				=> $sale->format_type(),
		isrc				=> $sale->isrc(),
		product_type		=> $sale->product_type(),
		service_product_id	=> $sale->service_product_id(),
		track_num			=> $sale->track_num,
		track				=> $sale->track_name,
		upc					=> $sale->upc,
		outlet				=> $sale->outlet,
	};

	my $result = $matcher->FindBestMatch(data => $matchData, min_match_level => 90, skip_rec => 1);
	if (File::Sale::STATUS_MATCH == $result->ImportStatus)
	{
		my $matchingProductID = $result->ProductIDs->[0];
		Common::Log::Print(" sale " . $sale->sale_id . " MATCHES product $matchingProductID");
		$matchCount++;

		my $units = $sale->units();
		if ($sale->sales() > 0 || $sale->returns() > 0)
		{
			$units = $sale->sales() - $sale->returns();
		}
		my $revenue = $units * $sale->price();
		$unitSum += $units;
		$revenueSum += $revenue;


		# Ok... Let's go ahead and re-assign these product ids.o
		#
		$sale->product_id($matchingProductID);
		$sale->save();
	}
	elsif (File::Sale::STATUS_MAPPED == $result->ImportStatus
	 || File::Sale::STATUS_AUTO_MAPPED == $result->ImportStatus)
	{
		Common::Log::Print("MAPPED SALE: ", $sale, " MATCH: ", $result);

		my $matchingProductID = $result->ProductIDs->[0];
		$sale->product_id($matchingProductID);
        $sale->map_id($result->MapID);
		$sale->import_status($result->ImportStatus());
		$sale->save();
	}
	else
	{
		Common::Log::Print(" sale " . $sale->sale_id . " NO MATCH", $sale, $result);
		Common::Log::Print("sale " . $sale->sale_id . ", file " . $sale->file_id . ", line " . $sale->line_num);
		
		push @{$badFileSale{$sale->file_id}}, $sale->sale_id;
	}
}


# Let's look again at the files we might need to 'split' - Let's see if we already have a split file in period 0.
#

foreach my $badFileID (keys %badFileSale)
{
	my $badSales = $badFileSale{$badFileID};

	my $file = Raptor::DB::Item::File->Lookup(file_id => $badFileID);
	my $childFile;

	my $parentFileID = $badFileID;
	while (my $f = Raptor::DB::Item::File->Lookup(parent_file_id => $parentFileID))
	{
		$childFile = $f;
		$parentFileID = $childFile->file_id;
	}
	
	Common::Log::Print("FILE: $badFileID, period " . $file->period_id() . "  Sale count: " . scalar @$badSales);
	if ($childFile)
	{
		Common::Log::Print("  LEAF CHILD: " . $childFile->file_id() . ", period " . $childFile->period_id());
        $file = $childFile;
	}

    # !!! One thing that needs to be considered:  If a file only has one sale, or if all the sales in a file
    # !!! (that is in a closed period) are 'bad', then we don't need to split the file: We need to re-open it.
    #
    # So let's get a count of the number of sales first.
    #
    my $allOriginalSales = Raptor::DB::Item::Sale->GetAll("SELECT * FROM sale WHERE file_id = $badFileID");
    my $originalSaleCount = $allOriginalSales->size();
    my $badSaleCount = scalar(@$badSales);

    Common::Log::Print("original sale count: $originalSaleCount,  bad sale count: $badSaleCount");



    # BEFORE we split any files, we need to re-set these 'bad' sales to appear
    # unmatched.   Otherwise the Split code will not work correctly.
    #
    foreach my $badSaleID (@$badSales)
    {
        my $sale = Raptor::DB::Item::Sale->Lookup(sale_id => $badSaleID);
        $sale->product_id(undef);
        $sale->map_id(undef);
        $sale->import_status(File::Sale::STATUS_NOMATCH);
        $sale->save();

        Common::Log::Print("  re-set sale $badSaleID");
    }


    my $oldFileID = $file->file_id();
    my $newFileID;
    if ($badSaleCount == $originalSaleCount)
    {
        # All sales are bad.
        # We need to possibly re-open the file, but the file_id will not change.
        #
        if (0 != $file->period_id())
        {
            Common::Log::Print("  re-opening file " . $file->file_id());
            $file->period_id(0);
            $file->file_status(4);
            $file->save();

            $newFileID = $file->file_id();
        }
    }
    elsif (0 == $file->period_id)
    {
        # Have a split file already, just move the sales.
        #
        Common::Log::Print("  using existing child file " . $file->file_id());
        $newFileID = $file->file_id();
    }
    else
    {
        # Need to split
        #
        Common::Log::Print("  Need to split file");
        my $oldFile = RPS::File::File->new(file_id => $file->file_id());
        my $newFile = $oldFile->Split();
        $newFileID = $newFile->FileID();

        # The Split method clones the original file, which is _usually_ in period 0, and Open.
        # Meaning, it doesn't bother to actually _set_ these fields. Since we are splitting a closed
        # file in a different period, we need to set these fields explicitly.
        #
        $newFile->PeriodID(0);
        $newFile->FileStatus(4);
        $newFile->Save();
        Common::Log::Print("  new file id: $newFileID");
    }

    # This may be redundant if the file was actually split, but should be harmless.
    #
    foreach my $badSaleID (@$badSales)
    {
        my $sale = Raptor::DB::Item::Sale->Lookup(sale_id => $badSaleID);

        # This may be redundant with files that we just split, but it won't hurt.
        #
        $sale->file_id($newFileID);
        $sale->save();

        Common::Log::Print("  updated sale $badSaleID");
    }


    # Re-calculate summary data.
    #
    my $oldFile = RPS::File::File->new(file_id => $oldFileID);
    $oldFile->UpdateSummary(skip_conversion => 1);
    $oldFile->RecalculateRemainingExceptions();

    if ($oldFileID != $newFileID)
    {
        my $newFile = RPS::File::File->new(file_id => $newFileID);
        $newFile->UpdateSummary(skip_conversion => 1);
        $newFile->RecalculateRemainingExceptions();
    }
}


Common::Log::Print("UNIT SUM RECOVERED: $unitSum   REVENUE RECOVERED: $revenueSum");
