package BookPub::Import::Importer::Amazon::Amazon1;

use strict;

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

use lib '/app/tools/bookpub/lib';
use BookPub::DB::Item::Sale;
use BookPub::Import::SaleRec;
use base 'BookPub::Import::Importer';

sub _getFieldMap {
    assert( 0, 'override' );
}

sub _getColumnValue {
    my ( $self, $line, $colName ) = @_;

    return undef unless defined $self->{_fieldMap}->{$colName};
    return $line->[ $self->{_fieldMap}->{$colName} ];
}

# currently, agency model type sales are not mixed with non-agency sales so the 'agency' flag can be
# set at a file level.  override _isAgency in the subclass if it IS an agency model file
sub _isAgency { return 'N'; }

#public methods

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

    my $lines = $args{lines};
    my $fName = $args{file}->OrigFileName();

    #my $fName = $args{OrigFileName};
    my $saleCount;

    $self->{_fieldMap} = $self->_getFieldMap();
    my $agency = $self->_isAgency();

    my ( $beginDate, $endDate ) = $self->_determineDateRange( $lines, $fName );
    unless ($beginDate) {
        $self->errstr('failed to get dates');
        return;
    }

    my %errMsg = ();

    # Just skip the first line:  It's the header.
    for ( my $i = 1 ; $i < scalar @$lines ; $i++ ) {
        my $line = $lines->[$i];

        my $amazonID     = $self->_getColumnValue( $line, 'amazon_id' );
        my $isbn10       = $self->_getColumnValue( $line, 'isbn10' );
        my $isbn13       = $self->_getColumnValue( $line, 'isbn13' );
        my $isbnDigital  = $self->_getColumnValue( $line, 'isbn_digital' );
        my $title        = $self->_getColumnValue( $line, 'title' );
        my $author       = $self->_getColumnValue( $line, 'author' );
        my $imprint      = $self->_getColumnValue( $line, 'imprint' );
        my $format       = $self->_getColumnValue( $line, 'format' );
        my $sales        = $self->_getColumnValue( $line, 'sales' );
        my $returns      = $self->_getColumnValue( $line, 'returns' );
        my $units        = $self->_getColumnValue( $line, 'net_units' );
        my $adjustments  = $self->_getColumnValue( $line, 'adjustments' );
        my $listPrice    = $self->_getColumnValue( $line, 'list_price' );
        my $discount     = $self->_getColumnValue( $line, 'discount' );
        my $revenue      = $self->_getColumnValue( $line, 'revenue' );
        my $currencyCode = $self->_getColumnValue( $line, 'currency_code' ) || 'USD';
        my $countryCode  = $self->_getColumnValue( $line, 'country_code' ) || 'US';

        $revenue =~ s/,//g;
        $revenue *= -1 if ( $revenue =~ s/[()]//g );    # for the tsv version

        # force perl to convert certain $ type strings to numbers
        # mostly for the case of 0.00 to simplify the following non-zero test of revenue
        $revenue   += 0;
        $listPrice += 0;

        # we _should_ require some sort of isbn, but amazon is reporting some sales with no isbn
        # so we'll put title in the 'or' list
        unless (( $units or $revenue )
            and ( $title or $isbnDigital or $isbn10 or $isbn13 ) ) {
            Common::Log::Print( 'skip ' . $i + 1 ) if $units;    # don't care bout all the rows with 0 units
            next;
        }

        $discount /= 100 if ( $discount > 1 );

        # The vast majority of the time, if there is a ':' in the title, it signifies the
        # start of the subtitle.
        # Note, though, that sometimes there are more than 1 ':'.  I don't want to strip out any data.
        # So we'll assume the _last_ ':' signifies the start of the subtitle.
        #
        my $subtitle;
        ( $title, $subtitle ) = BookPub::Import::Importer::ParseTitleAndSubtitle($title);

        my $formatCode = $self->_parseFormat($format);
        if ( !$formatCode && !defined $errMsg{$format} ) {
            $self->errstr('unknown format');
            Common::Log::Print("Unrecognized format type '$format'");
            $errMsg{$format} = 1;
        }

        my ( $unitPrice, $discountCalc );
        if ($units)    # units could be 0
        {
            eval {
                $unitPrice = abs( $revenue / $units );
                $discountCalc = BookPub::Import::Importer::CalculateDiscount( $unitPrice, $listPrice ) if $listPrice;
            };
            Common::Log::Print("oops! units: '$units' listprice: '$listPrice' ($i)") if ($@);
        }

        my $saleRec = BookPub::Import::SaleRec->new();

        $saleRec->lineNum( $i + 1 );
        $saleRec->dateBegin($beginDate);
        $saleRec->dateEnd($endDate);

        $saleRec->formatType($formatCode);
        $saleRec->productType(BookPub::DB::Item::Sale::kProductTypeEBook);
        $saleRec->purchaseType(BookPub::DB::Item::Sale::kPurchaseTypeDownload);
        $saleRec->serviceProductID($amazonID);

        $saleRec->isAgency($agency);
        $saleRec->units($units);
        $saleRec->listPrice($listPrice);
        $saleRec->discount( $discountCalc || $discount );
        $saleRec->unitPrice( $unitPrice   || $listPrice );
        $saleRec->revenue($revenue);
        $saleRec->currencyCode($currencyCode);
        $saleRec->countryCode($countryCode);

        # !!! These are DIGITAL sales.  Not going to save the physical isbns, for now...
        $saleRec->rIsbn13($isbnDigital);
        $saleRec->rTitle($title);
        $saleRec->rSubtitle($subtitle);
        $saleRec->rAuthor($author);
        $saleRec->rImprint($imprint);
        $saleRec->rFormat($format);

        $saleRec->rSales($sales);
        $saleRec->rReturns($returns);
        $saleRec->rAdjustments($adjustments);
        $saleRec->rListPrice($listPrice);
        $saleRec->rDiscount($discount);
        $saleRec->rRevenue($revenue);

        #$args{dumper}($saleRec);
        $self->_insertSale( sale => $saleRec );
        $saleCount++;
    }

    return $saleCount;
}

# unfortunately, they use the 1st day of the next month in the 'date' column of the report so we'll
# look at the file name to get a hint of what month it was meant for.  if the month in the date
# col matches the end of the date range from the file name, we'll use the beginning of the date range
# to pass into _getDates, otherwise we'll fall back to whats in the date col
sub _determineDateRange {
    my ( $self, $lines, $fileName ) = @_;
    my $dateStr = $lines->[ $self->{_fieldMap}{date}[0] ][ $self->{_fieldMap}{date}[1] ];

    unless ( $dateStr =~ m/^(\d+)\D\d+\D\d+/ ) {
        Common::Log::Print("failed to match date from '$dateStr'");
        return;
    }
    my $detailMonth = $1;

    unless ( $fileName =~ m/\D(2\d+)\D(2\d+)\./ ) {
        Common::Log::Print("failed to match date from '$fileName'");
        return;
    }
    my ( $nameDateStart, $nameDateEnd ) = ( $1, $2 );

    my ($nameMonthStart) = $nameDateStart =~ m/2\d\d\d(\d\d)\d+/;
    my ($nameMonthEnd)   = $nameDateEnd =~ m/2\d\d\d(\d\d)\d+/;
    Common::Log::Print(
        "All the freaking dates: detailMonth = '$detailMonth', nameDateStart = '$nameDateStart', nameDateEnd = '$nameDateEnd'");
    Common::Log::Print("nameMonthStart = '$nameMonthStart', nameMonthEnd = '$nameMonthEnd'");

    return unless ( $nameMonthEnd == $detailMonth and ( $nameMonthEnd - $nameMonthStart == 1 or $nameMonthEnd - $nameMonthStart == -11 ) );

    Common::Log::Print("get dates using $nameDateStart");
    return $self->_getDates( date_begin => $nameDateStart );
}

###
1;    # Play nicely.
###
