#------------------------------------------------------------
# Copyright (C) 2007 RoyaltyShare, Inc.   All Rights Reserved
# $Id$
#------------------------------------------------------------
package RPS::DB::Item::ConsolidatedArtistRoyaltyRunMissedSaleLog;

use strict;
use warnings;

use lib '/app/tools/common/lib';
use lib '/app/tools/rps/lib';
use Common::Util qw(escape_mysql_regexp escape_mysql_like);
use Common::DB::ItemCollection;
use Common::Assert;
use Common::RSApp;
use Common::Log;
use RPS::DB::Item::ArtistRoyaltyRunMissedSaleLog;
use RPS::DB::Item::Product;
use RPS::DB::Item::Album;
use RPS::DB::Item::Track;
use RPS::DB::Item::NewArtistContract;
use RPS::DB::Item::Artist;
use RPS::DB::Item::ProductType;

use Common::DB::Item;
use base 'Common::DB::Item';

use constant kTable => 'consolidated_artist_royalty_run_missed_sale_log';
use constant kDB => Common::DB::Item::kClientDB();


sub GetByRunID
{
    my ($class, $id) = @_;

    my $sql = "SELECT * FROM " . kTable . " WHERE artist_royalty_run_id=$id ORDER BY catalog_number, album_title, track_title, reason, details, units DESC";
    return $class->SUPER::GetAll($sql);
}

sub DeleteByRunID
{
    my ($class, $id) = @_;

    my $sql = "DELETE FROM " . kTable . " WHERE artist_royalty_run_id=$id";
    my $dbo = Common::RSApp::GetClientDB();
    $dbo->DoCmd($sql);
}


# This method builds the consolidated log from data in the unconsolidated log.
#
sub BuildForRun
{
    my ($class, $runID) = @_;
    assert($runID);

    my $sql = "SELECT * FROM artist_royalty_run_missed_sale_log WHERE artist_royalty_run_id=$runID"
     . " ORDER BY reason,details,artist_contract_id,album_id,track_id,product_id,sale_id";

    my $lastItem;
    my $units;
    my $revenue;
	my $logLines = RPS::DB::Item::ArtistRoyaltyRunMissedSaleLog->GetAll($sql);
    while (my $item = $logLines->next())
    {
        # Special case for the first line, since there won't be a 'last line'.
        #
        if ($lastItem)
        {
            # Keep consolidating as long as the data doesn't change.
            #
            if (_shouldConsolidateItems($lastItem, $item))
            {
                # We can do our 'dupe' check here:  Don't consolidate if we already have
                # this sale and contract id paid.
                #
                no warnings;
                if ($lastItem->artist_contract_id() != 0
                 && $lastItem->sale_id() == $item->sale_id())
                {
                    next;
                }
            }
            else
            {
                _writeConsolidatedLog($lastItem, $units, $revenue, $runID );
                $units = 0;
                $revenue = 0;
            }
        }

        $lastItem = $item;
        $units += $lastItem->units;
        $revenue += $lastItem->total_revenue;
    }

    # Log the last line (assuming there were _any_ lines...)
    #
    if ($lastItem)
    {
        _writeConsolidatedLog($lastItem, $units, $revenue, $runID);
    }
}

sub _shouldConsolidateItems
{
    my ($lastItem, $item) = @_;

# !!! We may need to make the consolidation logic more elaborate.
# !!! For instance, I don't really want to differentiate 'bad product id'
# !!! errors by product_id.
#

    no warnings; # I don't CARE if the value is uninitialized!
    if ('Bad product id' eq $item->details && 'Bad product id' eq $lastItem->details)
    {
        # Consolidate all of these...
        #
        return 1;
    }
    else
    {
        if ($lastItem->artist_contract_id == $item->artist_contract_id
         && $lastItem->album_id == $item->album_id
         && $lastItem->track_id == $item->track_id
         && $lastItem->product_id == $item->product_id
         && $lastItem->reason eq $item->reason
         && $lastItem->details eq $item->details)
        {
            return 1;
        }
    }

    return 0;
}


sub _writeConsolidatedLog
{
    my ($lastItem, $units, $revenue, $runID) = @_;

    my $newLogEntry = RPS::DB::Item::ConsolidatedArtistRoyaltyRunMissedSaleLog->Create();

    $newLogEntry->artist_royalty_run_id($runID);
    $newLogEntry->reason($lastItem->reason());
    $newLogEntry->details($lastItem->details());
    $newLogEntry->units($units);
    $newLogEntry->total_revenue($revenue);


    # Fetch all the names, titles, product types, etc., that match the ids.
    #
    if ($lastItem->product_id())
    {
        $newLogEntry->product_id( $lastItem->product_id() );
        my $product = RPS::DB::Item::Product->Lookup(product_id => $lastItem->product_id() );
        if ($product)
        {
            $newLogEntry->product_type_id( $product->product_type_id() );
            $newLogEntry->product_type( _idToProductType($product->product_type_id() ) );
        }
    }


    my $artistID;
    if ($lastItem->album_id())
    {
        $newLogEntry->album_id( $lastItem->album_id() );
        my $album = RPS::DB::Item::Album->Lookup(album_id => $lastItem->album_id());
        if ($album)
        {
            $newLogEntry->album_title($album->title());
            $newLogEntry->catalog_number($album->catalog_number());

            $artistID = $album->artist_id();
        }
    }

    if ($lastItem->track_id())
    {
        $newLogEntry->track_id( $lastItem->track_id() );
        my $track = RPS::DB::Item::Track->Lookup(track_id => $lastItem->track_id());
        if ($track)
        {
            $newLogEntry->track_title($track->title());
            $artistID = $track->artist_id;
        }
    }

    if ($lastItem->artist_contract_id())
    {
        $newLogEntry->artist_contract_id($lastItem->artist_contract_id());
        my $artistContract = RPS::DB::Item::NewArtistContract->Lookup(artist_contract_id => $lastItem->artist_contract_id());
        if ($artistContract)
        {
            $newLogEntry->artist_contract_title($artistContract->title());
        }
    }

    if ($artistID)
    {
        my $artist = RPS::DB::Item::Artist->Lookup(artist_id => $artistID);
        if ($artist)
        {
            $newLogEntry->artist_name($artist->name());
        }
    }

    $newLogEntry->save();
}


my $gProductTypeIDMap;
sub _idToProductType
{
    my ($id) = @_;

    if ($gProductTypeIDMap)
    {
        $gProductTypeIDMap = {};

        my $all = RPS::DB::Item::ProductType->GetAll();
        while (my $pt = $all->next())
        {
            $gProductTypeIDMap->{$pt->product_type_id} = $pt->description;
        }
    }

    my $productTypeName = '(Missing)';

    if ($gProductTypeIDMap->{$id})
    {
        $productTypeName = $gProductTypeIDMap->{$id};
    }

    return $productTypeName;
}


1;
