package BookPub::Import::Importer::Amazon::Version5;

use strict;

use lib '/app/tools/bookpub/lib';
use base 'BookPub::Import::Importer';

use Date::Calc qw( Add_Delta_YM );

sub _headerIdentifier { rTitle => qr/Title|Titre \(Title\)/ }

sub _fieldMap {
    {
        dateBegin              => 'A',
        serviceProductID       => 'B',
        currencyCode           => 'U',
        countryCode            => 'V',
        rFormat                => 'I',
        isbn                   => 'E',
        rTitle                 => 'F',
        rAuthor                => 'G',
        rImprint               => 'H',
        rUnits                 => 'L',
        rSales                 => 'J',
        rReturns               => 'K',
        rAdjustments           => 'N',
        rPurchasePrice         => 'O',
        rPurchasePriceCurrency => 'P',
        rListPrice             => 'Q',
        rListPriceCurrency     => 'R',
        rDiscount              => 'S',
        rRevenue               => 'T',
    };
}

sub _useIsSaleRec { 1 }
sub rServiceName  { 'Amazon' }
sub purchaseType  { BookPub::DB::Item::Sale::kPurchaseTypeDownload }
sub productType   { BookPub::DB::Item::Sale::kProductTypeEBook }
sub rProductType  { BookPub::DB::Item::Sale::kProductTypeEBook }

sub priceType {
    my $self = shift;

    my $clientID = Common::RSApp::GetClientID;
    return 'agency' if $clientID =~ /^355$/;                # HUK
    return 'rrp'    if $clientID =~ /^(?:314|328|361)$/;    # Bloomsbury

    if ( $clientID =~ /^318$/ ) {                           # MMUS
        return $self->countryCode =~ /^(?:US|CA)$/i
            ? 'agency'
            : 'rrp';
    }
}

sub countryCode {
    my $self     = shift;
    my $code     = $self->_getByFieldName('countryCode');
    my $filename = $self->filename();

    if ( !defined $code || $code eq '' ) {
        if ( $filename =~ /(?:_(\w{2})_|_(\w{2})\.)/ ) {
            my $cc = $1 || $2;
            my $obj = Common::Country->Get($cc);
            if ($obj) {
                return $obj->alpha2;
            } else {
                $self->fail("Invalid country code: $cc");
            }
        } else {
            $self->fail("Couldn't find country code in filename");
        }
    } else {
        my $obj = Common::Country->Get($code);
        if ($obj) {
            return $obj->alpha2;
        } else {
            $self->fail("Invalid country code: $code");
        }
    }
}

sub _getDateBegin {
    my $self = shift;
    my $date = $self->_getByFieldName('dateBegin') || return;
    my ( $year, $month, $day );

    if ( $date && $date =~ /^(\d{1,2})[-\/](\d{1,2})[-\/](?:20)?(\d{2})$/ ) {
        $year = "20$3";
        $month;
        $day = 1;

        # Trying to detect euro style dates.
        # Amazon always sets the day to 1, so we'll check for that.
        if ( $1 == 1 ) {
            $month = $2;
        } else {
            $month = $1;
        }

        ( $year, $month, $day ) = Add_Delta_YM( $year, $month, $day, 0, -1 );

    } elsif ( $date && $date =~ /^(\d{4})[-\/](\d{1,2})[-\/](\d{1,2})$/ ) {
        $year = $1;
        $month;
        $day = 1;

        # Trying to detect euro style dates.
        # You would think we could count on the order for this one, but nope.
        # Amazon always sets the day to 1, so we'll check for that.
        if ( $2 == 1 ) {
            $month = $3;
        } else {
            $month = $2;
        }

        ( $year, $month, $day ) = Add_Delta_YM( $year, $month, $day, 0, -1 );
    }
    return sprintf( "%04d-%02d-%02d", $year, $month, $day );
}

sub _dateNormalization { 'month' }

sub rRevenue {
    my $self = shift;

    my $revenue = $self->_getByFieldName('rRevenue');

    if ( $revenue =~ s/[\(\)]//g ) {
        $revenue *= -1;
    }

    # If there are adjustments and units, we need to calculate what the revenue would be without the
    # adjustments because we're going to log those in a separate sale record.
    my $adjustments = $self->_getByFieldName('rAdjustments');
    if ( $adjustments && $self->units ) {

        my $discount = $self->rDiscount;
        if ( $discount > 1 ) {
            $discount /= 100;
        }

        $revenue = Common::RSMath::round( $self->rPurchasePrice * ( 1 - $discount ), 2 ) * $self->units;
    }

    return $revenue;
}

# We're going to zero these out if there are units
# so that they don't get added to the sale records and the adjustment records.
sub rAdjustments {
    my $self        = shift;
    my $adjustments = $self->_getByFieldName('rAdjustments');
    my $units       = $self->_getByFieldName('rUnits');
    if ( $adjustments && $units ) {
        return 0;
    } else {
        return $adjustments;
    }
}

sub rListPriceCurrency {
    my $self              = shift;
    my $listPriceCurrency = $self->_getByFieldName('rListPriceCurrency');
    my $revenueCurrency   = $self->_getByFieldName('currencyCode');

    # For Macmillan, RLPG, and Wiley, we're going to set the list price currency to the revenue currency.
    # We'll also be converting the list price with the conversion rate.
    if ( $self->listPriceRequired && $listPriceCurrency && $listPriceCurrency ne $revenueCurrency ) {
        $listPriceCurrency = $revenueCurrency;
    }

    return $listPriceCurrency;
}

sub rListPrice {
    my $self              = shift;
    my $listPrice         = $self->_getByFieldName('rListPrice');
    my $listPriceCurrency = $self->_getByFieldName('rListPriceCurrency');
    my $revenueCurrency   = $self->_getByFieldName('currencyCode');

    # For Macmillan, RLPG, and Wiley, we're going to convert the list price if
    # it's in a different currency than the revenue is.
    #
    if ( $self->listPriceRequired && $listPriceCurrency && $listPriceCurrency ne $revenueCurrency && $listPrice != 0 ) {
        $listPrice =~ s/,//g;
        my $revenue  = $self->rRevenue;
        my $units    = $self->units();
        my $discount = $self->rDiscount;
        if ( $discount > 1 ) {
            $discount /= 100;
        }

        # If the discount is 100%, we can't derive the conversion rate so we have to default to 0.
        if ( $discount == 1 ) {
            $listPrice = 0;
        } elsif ($units) {
            my $conversionRate = $revenue / ( $listPrice * $units * ( ( 1 - $discount ) / 1 ) );
            $listPrice *= $conversionRate;
        }
    }

    return abs($listPrice);
}

sub _processLine {
    my $self = shift;
    my $id   = $self->serviceProductID();

    if ( $id && ( lc($id) =~ /invoice number/ || lc($id) eq 'cogs' ) ) {
        $self->{_endOfData} = 1;
    }

    return $self->SUPER::_processLine(@_);
}

sub rFormat {
    my $self = shift;

    my $rFormat = $self->_getByFieldName('rFormat') || '';
    if ( $rFormat =~ /^Kindl eBook$/i ) {
        return 'Kindle eBook';
    }

    return $rFormat;
}

sub preProcessLine {
    my $self = shift;

    my $adjustments = $self->_getByFieldName('rAdjustments');

    # create an adjusted revenue record if necessary
    if ( $adjustments && $self->units ) {

        my $revenue = $self->_getByFieldName('rRevenue');
        if ( $revenue =~ s/[\(\)]//g ) {
            $revenue *= -1;
        }

        $revenue = Common::RSMath::round( $revenue, 2 );

        my $rRevenue = $self->rRevenue;

        $rRevenue = Common::RSMath::round( $rRevenue, 2 );

        $revenue -= $rRevenue;

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

        # These are the fields we need to change for this record.
        $sale->rUnits(0);
        $sale->units(0);
        $sale->rAdjustments($adjustments);
        $sale->rRevenue($revenue);
        $sale->revenue($revenue);

        # And these fields can just use the regular values.
        $sale->dateBegin( $self->dateBegin() );
        $sale->dateEnd( $self->dateEnd() );
        $sale->serviceID( $self->serviceID );
        $sale->importStatus( $self->importStatus );
        $sale->productType( $self->productType );
        $sale->formatType( $self->formatType );
        $sale->priceTypeID( $self->priceTypeID );
        $sale->purchaseType( $self->purchaseType );
        $sale->serviceProductID( $self->serviceProductID );
        $sale->isAgency( $self->isAgency );
        $sale->listPrice( $self->listPrice );
        $sale->discount( $self->discount );
        $sale->currencyCode( $self->currencyCode );
        $sale->countryCode( $self->countryCode );
        $sale->rFormat( $self->rFormat );
        $sale->rPriceType( $self->rPriceType );
        $sale->rPurchaseType( $self->rPurchaseType );
        $sale->rProductType( $self->rProductType );
        $sale->rClientProductID( $self->rClientProductID );
        $sale->rIsbn10( $self->rIsbn10 );
        $sale->rIsbn13( $self->rIsbn13 );
        $sale->rServiceName( $self->rServiceName );
        $sale->rDistributor( $self->rDistributor );
        $sale->rTitle( $self->rTitle );
        $sale->rSubtitle( $self->rSubtitle );
        $sale->rAuthor( $self->rAuthor );
        $sale->rImprint( $self->rImprint );
        $sale->rPurchasePrice( $self->rPurchasePrice );
        $sale->rPurchasePriceCurrency( $self->rPurchasePriceCurrency );
        $sale->rListPrice( $self->rListPrice );
        $sale->rListPriceCurrency( $self->rListPriceCurrency );
        $sale->rDiscount( $self->rDiscount );
        $sale->rCOGS( $self->rCOGS );
        $sale->rUnitPrice( $self->rUnitPrice );

        $sale->lineNum( $self->linenum );

        $self->SUPER::_insertSale( sale => $sale );
    }
}

sub _isSaleRec {
    my $self = shift;

    # If we've set the end of data flag in processLine, we are done.
    return if ( $self->{_endOfData} );

    return $self->SUPER::_isSaleRec();
}

1;
