#!/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 lib '/app/tools/rps/lib';
use RPS::DB::Item::MechanicalCarryover;
use RPS::DB::Item::TrackLicense;
use RPS::DB::Item::Track;
use RPS::DB::Item::TrackContract;
use RPS::DB::Item::Master;
use RPS::DB::Item::Album;

#use RPS::DB::Item::License;
use RPS::DB::Item::LicenseReserve;
use RPS::DB::Item::LicenseReserveLiquidation;
use RPS::DB::Item::StatRate;
use RPS::DB::Item::ProductTrack;
use RPS::DB::Item::Song;

use RPS::DB::Item::Publisher;
use RPS::DB::Item::Product;
use RPS::DB::Item::ControlledComposition;

use RPS::DB::Item::AlbumContract;
use RPS::DB::Item::MechanicalRun;
use RPS::DB::Item::MechanicalStatement;
use RPS::DB::Item::MechanicalStatementItem;
use RPS::DB::Item::MechanicalStatementItem;
use RPS::DB::Item::MechanicalStatementTrack;
use RPS::DB::Item::MechanicalStatementLicense;
use RPS::DB::Item::MechanicalStatementAdjustmentItem;
use RPS::DB::Item::SaleMechanicalStatementItemMap;

use RPS::License::TrackLicense;
use RPS::License::TrackLicenseList;
use RPS::DB::Item::NewArtistContract;
use RPS::DB::Item::ReserveLiquidation;

# INTEGRATION
#
# Adding some new fields.
# Plus, we're taking the 'client_album_id' field from raptor and adding it.
#

my $gVerbosityLevel = 1;

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

my $clientAlbumIDMap = _readClientAlbumIDFromRaptor( $options{origClientID} );

_alterAlbum( $options{clientID}, $clientAlbumIDMap );

sub _readClientAlbumIDFromRaptor {
    my ($raptorClientID) = @_;
    assert($raptorClientID);

    my %map;
    my $appSingleton = Common::RSApp->new( clientID => $raptorClientID );

    # Can't use a fancy db abstraction layer safely, so we'll query this the old fashioned way
    #
    my $dbo = Common::RSApp::GetClientDB();
    my $sql = "select album_id, client_album_id, company_id, vendor_id, location_id from album";
    my $sth = $dbo->DoCmd($sql);
    while ( my $hr = $sth->fetchrow_hashref() ) {
        $map{ $hr->{album_id} } = {
            clientAlbumID => $hr->{client_album_id},
            companyID     => $hr->{company_id},
            vendorID      => $hr->{vendor_id},
            locationID    => $hr->{location_id},
        };
    }

    return \%map;
}

sub _alterAlbum {
    my ( $clientID, $clientAlbumIDMap ) = @_;
    assert($clientID);
    assert($clientAlbumIDMap);

    my $appSingleton = Common::RSApp->new( clientID => $clientID );

    # Add the client_album_id column
    #
    my $dbo = Common::RSApp::GetClientDB();
    my $sql = "ALTER TABLE album ADD COLUMN client_album_id varchar(50)";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }
    $sql = "ALTER TABLE album ADD COLUMN company_id varchar(50)";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }
    $sql = "ALTER TABLE album ADD COLUMN vendor_id varchar(50)";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }
    $sql = "ALTER TABLE album ADD COLUMN location_id varchar(50)";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }
    $sql = "ALTER TABLE album ADD COLUMN title_clean varchar(255)";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }

    $sql = 'ALTER TABLE album ADD KEY `client_album_id` (`client_album_id`)';
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }
    $sql = 'ALTER TABLE album ADD KEY `title_clean` (`title_clean`)';
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }

    # Add the custom columns
    #
    $sql = "ALTER TABLE album ADD COLUMN custom_1 varchar(255)";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }
    $sql = "ALTER TABLE album ADD COLUMN custom_2 varchar(255)";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }
    $sql = "ALTER TABLE album ADD COLUMN custom_3 varchar(255)";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }

    # I need to set the title_clean field.   To insure consistency, I'll derive it
    # from the current title.
    #
    $sql = "SELECT album_id, title from album";
    my $sth = $dbo->DoCmd($sql);
    while ( my $hr = $sth->fetchrow_hashref ) {
        $clientAlbumIDMap->{ $hr->{album_id} }{titleClean} = Common::Utils::clean_name( $hr->{title} );
    }

    while ( my ( $albumID, $raptorData ) = each(%$clientAlbumIDMap) ) {
        my $clientAlbumID = $raptorData->{clientAlbumID};
        my $companyID     = $raptorData->{companyID};
        my $vendorID      = $raptorData->{vendorID};
        my $locationID    = $raptorData->{locationID};
        my $upcAlt        = $raptorData->{upcAlt};
        my $titleClean    = $raptorData->{titleClean};

        $sql =
            "UPDATE album SET client_album_id = "
          . $dbo->DBQuote($clientAlbumID)
          . ", company_id = "
          . $dbo->DBQuote($companyID)
          . ", vendor_id = "
          . $dbo->DBQuote($vendorID)
          . ", location_id = "
          . $dbo->DBQuote($locationID)
          . ", title_clean = "
          . $dbo->DBQuote($titleClean)
          . " WHERE album_id = "
          . $albumID;
        if ( !$dbo->DoCmd($sql) ) {
            _report( "error " . $dbo->LastErrorStr() );
            return;
        }
    }
}

sub _alterProduct {
    _report("altering product table");

    # First, we'll add the new column.
    #
    _report("adding asset_id column");

    my $dbo = Common::RSApp::GetClientDB();
    my $sql = "ALTER TABLE product ADD COLUMN asset_id int(10) unsigned default NULL";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }

    # Now we'll move through the products, setting asset_id to the proper value.
    #
    my $productList = RPS::DB::Item::Product->GetAll();
    _report( "updating " . $productList->size() . " products" );
    while ( my $product = $productList->next() ) {
        if ( RPS::DB::Item::Product::kProductTypeDigitalTrack == $product->product_type_id ) {
            $product->asset_id( $product->track_id );
        } else {
            $product->asset_id( $product->album_id );
        }
        $product->save();
    }

    # Last, drop track_id and album_id
    #
    _report("dropping album_id");
    $sql = "ALTER TABLE product DROP COLUMN album_id";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }

    _report("dropping track_id");
    $sql = "ALTER TABLE product DROP COLUMN track_id";
    if ( !$dbo->DoCmd($sql) ) {
        _report( "error " . $dbo->LastErrorStr() );
        return;
    }

    _report("product table has been altered");
}

sub _usage {
    print "\nusage: $0 -o original client_id -c client_id [-V]\n";
    print "\n";
    print "Arguments:\n";
    print "\t-o <client_id>\t\tThe client_id of the Raptor client (from which we'll copy some stuff)\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 STDERR $string . "\n";
    }
}

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

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

    if ( !$opt{c} ) {
        _usage();
        exit(1);
    }
    $settings->{clientID} = $opt{c};
    if ( !$opt{o} ) {
        _usage();
        exit(1);
    }
    $settings->{origClientID} = $opt{o};

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