package BookPub::Sale::Report::Royalty::RandomHouseUK;

use strict;
use Template;
use Data::Dumper;

use lib '/app/tools/common/lib';
use Common::Log;
use Common::Client;
use Common::DB::ItemCollection;
use Common::DB::Item;
use Common::Util qw(formatFixedPoint);

use lib '/app/tools/bookpub/lib';
use BookPub::DB::Item::File;
use BookPub::DB::Item::Period;
use BookPub::DB::Item::Imprint;
use BookPub::DB::Item::ClientService;
use BookPub::DB::Item::BookContributor;
use BookPub::DB::Item::BookProduct;
use BookPub::DB::Item::PriceType;
use BookPub::DB::Item::ProductMarketPrice;

use BookPub::DB::Item::RoyaltyReport::RandomHouseUK;

use base 'BookPub::Sale::Report::Royalty';

# use constant kDB => Common::DB::Item::kClientDB;
# use constant OUTDIR_BASE => '/app/data/sale_report/tmp/';

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    $self->_init(@_);

    return $self;
}

sub _init {
    my $self = shift;
    my %args = @_;

    $self->SUPER::_init(%args);

    $self->{clientID} = $args{clientID} ? $args{clientID} : Common::RSApp::GetClientID();

    $self->{imprintMap}       = BookPub::DB::Item::Imprint->IDMap();
    $self->{clientServiceMap} = BookPub::DB::Item::ClientService->GetAllByRSServiceIDProdTypeCurrencyCode();

    $self->_createOutputDir();
}

sub create {
    my $self = shift;

    my $fileList =
      BookPub::DB::Item::File->GetServiceFilesByPeriodID( $self->periodID(), file_status => BookPub::DB::Item::File::STATUS_CLOSED );

    use constant kMonthRecordLimit => 9998;

    my $rptRows     = 0;
    my $rptUnits    = 0;
    my $rptRevenue  = 0;
    my %fileStats   = ();
    my %authorCache = ();
    my %svcBatch    = ();

    foreach my $svcID ( @{ $fileList->{_order} } ) {
        my @fileIDs = ();
        foreach my $fileRef ( @{ $fileList->{$svcID} } ) {
            my $fID = $fileRef->file_id;
            push( @fileIDs, $fID );
            $fileStats{$fID} = {

                #records => $fileRef->records,
                units   => $fileRef->units,
                revenue => $fileRef->revenue,

                #revenue => $fileRef->revenue || $fileRef->input_revenue,
            };
        }

        # init the service file stats hash
        # it will be used to validate against %fileStats (above) to ensure the rows printed
        # match the orig file specs
        my %svcFileStats = ();
        map { $svcFileStats{$_} = { records => 0, units => 0, revenue => 0 } } @fileIDs;

        foreach my $prodType ( keys %{ $self->{clientServiceMap}{$svcID} } ) {
            foreach my $currencyCode ( keys %{ $self->{clientServiceMap}{$svcID}{$prodType} } ) {
                foreach my $condition ( '>=', '<' ) {
                    my $collection = BookPub::DB::Item::RoyaltyReport::RandomHouseUK->GetReportData(
                        condition    => $condition,
                        serviceID    => $svcID,
                        fileIDs      => \@fileIDs,
                        productType  => $prodType,
                        currencyCode => $currencyCode,
                    );

                    next unless ( $collection->size );

                    my $svcMonthRecords = 0;
                    my $svcMonthUnits   = 0;
                    my $svcMonthRevenue = 0;
                    my $svcMonth        = 0;
                    my $cntRecords      = 0;
                    my %tmplVars;
                    while ( my $row = $collection->next() ) {
                        if ( $svcMonthRecords == 0 && $cntRecords == 0 ) {
                            $svcMonth = $row->period;

                            my $clientServiceID = $self->{clientServiceMap}{$svcID}{$prodType}{$currencyCode}{id};
                            $self->_printServiceHeader(
                                period        => $svcMonth,
                                service_id    => $svcID,
                                product_type  => $prodType,
                                currency_code => $currencyCode,
                                condition     => $condition,
                                batch         => ++$svcBatch{$clientServiceID}{$condition}{$svcMonth}{$currencyCode}{batch},
                            );
                        } elsif ( $svcMonth != $row->period || $svcMonthRecords >= kMonthRecordLimit ) {
                            $tmplVars{revenue} = formatFixedPoint( $tmplVars{revenue}, 2 );

                            $svcMonthRecords++;
                            $svcMonthUnits   += $tmplVars{units};
                            $svcMonthRevenue += $tmplVars{revenue};

                            $self->_printDetail(
                                isbn       => $tmplVars{isbn},
                                units      => $tmplVars{units},
                                list_price => $tmplVars{list_price},
                                discount   => $tmplVars{discount},
                                country    => $tmplVars{country}
                            );

                            $cntRecords = 0;
                            %tmplVars   = undef;

                            # CLOSE FILE

                            $rptRows    += $svcMonthRecords;
                            $rptUnits   += $svcMonthUnits;
                            $rptRevenue += $svcMonthRevenue;

                            $svcMonthRecords = 0;
                            $svcMonthUnits   = 0;
                            $svcMonthRevenue = 0;
                            $svcMonth        = $row->period;
                            $cntRecords      = 0;

                            my $clientServiceID = $self->{clientServiceMap}{$svcID}{$prodType}{$currencyCode}{id};

                            $self->_printServiceHeader(
                                period        => $svcMonth,
                                service_id    => $svcID,
                                product_type  => $prodType,
                                currency_code => $currencyCode,
                                condition     => $condition,
                                batch         => ++$svcBatch{$clientServiceID}{$condition}{$svcMonth}{$currencyCode}{batch},
                            );
                        }

                        my $agency          = $row->price_type_id == BookPub::DB::Item::PriceType::kPriceTypeAgency ? 'Y' : 'N';
                        my $free            = $row->free;
                        my $country         = $row->country;
                        my $state           = $row->state;
                        my $currency        = $row->currency;
                        my $conversion_rate = $row->conversion_rate;
                        my $product_id      = $row->product_id;
                        my $unit_price      = $row->unit_price;
                        $unit_price *= $conversion_rate if ( $currencyCode ne $currency );
                        $unit_price = formatFixedPoint( $unit_price, 2 );
                        my $list_price = formatFixedPoint( $row->list_price, 2 );
                        my $discount = '0.00';
                        $discount = formatFixedPoint( $row->discount, 2 ) if ( $row->discount > 0 );

                        if (
                            $cntRecords
                            && (   $agency ne $tmplVars{agency}
                                || $free ne $tmplVars{free}
                                || $country ne $tmplVars{country}
                                || $state ne $tmplVars{state}
                                || $currency ne $tmplVars{currency}
                                || $conversion_rate != $tmplVars{conversion_rate}
                                || $unit_price != $tmplVars{unit_price}
                                || $list_price != $tmplVars{list_price}
                                || $discount != $tmplVars{discount}
                                || $product_id != $tmplVars{product_id} )
                          ) {
                            $tmplVars{revenue} = formatFixedPoint( $tmplVars{revenue}, 2 );

                            $svcMonthRecords++;
                            $svcMonthUnits   += $tmplVars{units};
                            $svcMonthRevenue += $tmplVars{revenue};

                            $self->_printDetail(
                                isbn       => $tmplVars{isbn},
                                units      => $tmplVars{units},
                                list_price => $tmplVars{list_price},
                                discount   => $tmplVars{discount},
                                country    => $tmplVars{country}
                            );

                            $cntRecords = 0;
                            %tmplVars   = undef;
                        }

                        if ( $cntRecords == 0 ) {

                            # grouping items
                            $tmplVars{agency}          = $agency;
                            $tmplVars{free}            = $free;
                            $tmplVars{country}         = $country;
                            $tmplVars{state}           = $state;
                            $tmplVars{currency}        = $currency;
                            $tmplVars{conversion_rate} = $conversion_rate;
                            $tmplVars{product_id}      = $product_id;
                            $tmplVars{unit_price}      = $unit_price;
                            $tmplVars{list_price}      = $list_price;
                            $tmplVars{discount}        = $discount;

                            # the rest of what the detail lines need (that's static)
                            $tmplVars{record_type}  = 'D';
                            $tmplVars{sale_month}   = substr( $row->period, 4, 2 );
                            $tmplVars{sale_year}    = substr( $row->period, 0, 4 );
                            $tmplVars{isbn}         = $row->isbn;
                            $tmplVars{product_type} = BookPub::DB::Item::BookProduct->GetProductString( $row->onix_prod_code );
                            $tmplVars{title}        = $row->title;
                            $tmplVars{subtitle}     = $row->subtitle;
                            my $bookID = $row->book_id;
                            $authorCache{$bookID} ||= BookPub::DB::Item::BookContributor->GetAuthorNamesByBookID($bookID);
                            $tmplVars{author}  = $authorCache{$bookID};
                            $tmplVars{imprint} = $self->{imprintMap}{ $row->imprint_id };
                        }

                        my $fID     = $row->file_id;
                        my $revenue = $row->revenue;
                        $revenue *= $row->conversion_rate if ( $currencyCode ne $row->currency );
                        $svcFileStats{$fID}{records}++;
                        $svcFileStats{$fID}{units}   += $row->units;
                        $svcFileStats{$fID}{revenue} += $revenue;

                        # finally, the aggregated stuff
                        $tmplVars{units}   += $row->units;
                        $tmplVars{revenue} += $revenue;

                        $cntRecords++;
                    }

                    # print the last service trailer (and detail line)
                    $tmplVars{revenue} = formatFixedPoint( $tmplVars{revenue}, 2 );

                    $svcMonthRecords++;
                    $svcMonthUnits   += $tmplVars{units};
                    $svcMonthRevenue += $tmplVars{revenue};

                    $self->_printDetail(
                        isbn       => $tmplVars{isbn},
                        units      => $tmplVars{units},
                        list_price => $tmplVars{list_price},
                        discount   => $tmplVars{discount},
                        country    => $tmplVars{country}
                    );

                    # CLOSE FILE

                    $rptRows    += $svcMonthRecords;
                    $rptUnits   += $svcMonthUnits;
                    $rptRevenue += $svcMonthRevenue;
                }
            }
        }

        # now that we've completed all files for the current service, validate the
        # accumulated totals against the orig file totals
        foreach my $fID ( keys %svcFileStats ) {
            if (    #$fileStats{$fID}{records} != $svcFileStats{$fID}{records}
                $fileStats{$fID}{units} != $svcFileStats{$fID}{units}
                or abs( $fileStats{$fID}{revenue} - $svcFileStats{$fID}{revenue} ) > .01
              ) {
                Common::Log::Print("numbers don't match for file_id $fID");
                Common::Log::Print( 'file: ' . Dumper( $fileStats{$fID} ) );
                Common::Log::Print( 'reported: ' . Dumper( $svcFileStats{$fID} ) );
            }
        }
    }

    # ZIP FILES
}

sub _createOutputDir {
    my ( $self, %args ) = @_;

    my $outFilePath = $self->filePath();

    $outFilePath =~ s/\.tsv/\//;

    system("mkdir -p '$outFilePath'");

    $self->{outFilePath} = $outFilePath;
}

sub _openOutput {
    my ( $self, %args ) = @_;

    # close(OUT);
    if ( exists $self->{out} ) {
        close( $self->{out} );
        delete( $self->{out} );
    }

    my $outFilePath = $self->{outFilePath} . $args{custref} . ".tsv";

    print STDERR "Opening $outFilePath\n";

    unless ( open( $self->{out}, '>:utf8', $outFilePath ) ) {
        die "can't open output file ($outFilePath) - $!\n";
    }
}

sub _printServiceHeader {
    my ( $self, %args ) = @_;

    my @months = ( 'JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC' );

    my $credit = 'CR' if $args{condition} eq '<';

    my $custRef = 'RH'
      . $self->{clientServiceMap}{ $args{service_id} }{ $args{product_type} }{ $args{currency_code} }{name}
      . $months[ substr( $args{period}, 5, 2 ) - 1 ]
      . substr( $args{period}, 2, 2 )
      . $args{currency_code}
      . $credit
      . sprintf( '%02d', $args{batch} );

    $self->_openOutput( custref => $custRef );

    print { $self->{out} } "Digital Sales\n"
      . "Customer\t"
      . $self->{clientServiceMap}{ $args{service_id} }{ $args{product_type} }{ $args{currency_code} }{id} . "\n"
      . "Customer Ref\t"
      . $custRef . "\n";

    print { $self->{out} } "\t\t\t\tISBN\t\t\t\t\t\t\tNet Qty\t\t\tList Price\t\tDiscount Value\t\t\tISO Ctry Code\n";
}

sub _printDetail {
    my ( $self, %args ) = @_;

    print { $self->{out} } "\t\t\t\t$args{isbn}\t\t\t\t\t\t\t$args{units}\t\t\t$args{list_price}\t\t$args{discount}\t\t\t$args{country}\n";
}

1;

