package BookPub::Import::Importer::Amazon::Version8;

use strict;

use lib '/app/tools/common/lib';
use Common::Country;

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

use Date::Calc qw( Add_Delta_YM );

sub _headerIdentifier { ( rAuthor => qr/Author/ ) }

sub _fieldMap {
    my $self = shift;

    my %map = (
        8 => {
            dateBegin                => 'A',
            rFormat                  => 'I',
            rAuthor                  => 'G',
            rTitle                   => 'F',
            rIsbn13                  => 'E',
            rImprint                 => 'H',
            serviceProductID         => 'B',
            rReturns                 => 'K',
            rSales                   => 'J',
            rUnits                   => 'L',
            rAdjustments             => 'N',
            rListPrice               => 'Q',
            rListPriceCurrency       => 'R',
            rNativeListPrice         => 'Q',
            rNativeListPriceCurrency => 'R',
            rPurchasePrice           => 'O',
            rPurchasePriceCurrency   => 'P',
            rDiscount                => 'S',
            rRevenue                 => 'T',
            currencyCode             => 'U',
            rChannel                 => 'V',
        },
        65 => {
            dateBegin                => 'A',
            rFormat                  => 'I',
            rAuthor                  => 'G',
            rTitle                   => 'F',
            rIsbn13                  => 'E',
            rImprint                 => 'H',
            serviceProductID         => 'B',
            rReturns                 => 'K',
            rSales                   => 'J',
            rUnits                   => 'L',
            rAdjustments             => 'N',
            rListPrice               => 'Q',
            rListPriceCurrency       => 'R',
            rNativeListPrice         => 'Q',
            rNativeListPriceCurrency => 'R',
            rPurchasePrice           => 'O',
            rPurchasePriceCurrency   => 'P',
            rRevenue                 => 'U',
            currencyCode             => 'V',
            rChannel                 => 'W',
        },
        70 => {
            dateBegin                => 'A',
            rFormat                  => 'I',
            rAuthor                  => 'G',
            rTitle                   => 'F',
            rIsbn13                  => 'E',
            rImprint                 => 'H',
            serviceProductID         => 'B',
            rReturns                 => 'K',
            rSales                   => 'J',
            rUnits                   => 'L',
            rAdjustments             => 'N',
            rListPrice               => 'Q',
            rListPriceCurrency       => 'R',
            rNativeListPrice         => 'Q',
            rNativeListPriceCurrency => 'R',
            rPurchasePrice           => 'O',
            rPurchasePriceCurrency   => 'P',
            rDiscount                => 'S',
            rRevenue                 => 'T',
            currencyCode             => 'U',
            rModel                   => 'V',
        },
        79 => {
            dateBegin                => 'A',
            rFormat                  => 'I',
            rAuthor                  => 'G',
            rTitle                   => 'F',
            rIsbn13                  => 'E',
            rImprint                 => 'H',
            serviceProductID         => 'B',
            rReturns                 => 'K',
            rSales                   => 'J',
            rUnits                   => 'L',
            rAdjustments             => 'N',
            rListPrice               => 'Q',
            rListPriceCurrency       => 'R',
            rNativeListPrice         => 'Q',
            rNativeListPriceCurrency => 'R',
            rPurchasePrice           => 'O',
            rPurchasePriceCurrency   => 'P',
            rDiscount                => 'S',
            rRevenue                 => 'T',
            currencyCode             => 'U',
            rChannel                 => 'X',
        },
        81 => {
            dateBegin                => 'A',
            rFormat                  => 'I',
            rAuthor                  => 'G',
            rTitle                   => 'F',
            rIsbn13                  => 'E',
            rImprint                 => 'H',
            serviceProductID         => 'B',
            rReturns                 => 'K',
            rSales                   => 'J',
            rUnits                   => 'L',
            rAdjustments             => 'N',
            rListPrice               => 'Q',
            rListPriceCurrency       => 'R',
            rNativeListPrice         => 'Q',
            rNativeListPriceCurrency => 'R',
            rPurchasePrice           => 'O',
            rPurchasePriceCurrency   => 'P',
            rDiscount                => 'S',
            rRevenue                 => 'T',
            currencyCode             => 'U',
            rChannel                 => 'X',
        },
        82 => {
            dateBegin                => 'A',
            rFormat                  => 'I',
            rAuthor                  => 'G',
            rTitle                   => 'F',
            rIsbn13                  => 'E',
            rImprint                 => 'H',
            serviceProductID         => 'B',
            rReturns                 => 'K',
            rSales                   => 'J',
            rUnits                   => 'L',
            rAdjustments             => 'N',
            rListPrice               => 'Q',
            rListPriceCurrency       => 'R',
            rNativeListPrice         => 'Q',
            rNativeListPriceCurrency => 'R',
            rPurchasePrice           => 'O',
            rPurchasePriceCurrency   => 'P',
            rDiscount                => 'S',
            rRevenue                 => 'T',
            currencyCode             => 'U',
            rModel                   => 'X',
        },
    );

    return $map{ $self->_version };
}

sub _useIsSaleRec              { 1 }
sub _autoParseTitleAndSubtitle { 1 }
sub purchaseType               { BookPub::DB::Item::Sale::kPurchaseTypeDownload }
sub rPurchaseType              { BookPub::DB::Item::Sale::kPurchaseTypeDownload }
sub productType                { BookPub::DB::Item::Sale::kProductTypeEBook }
sub rProductType               { BookPub::DB::Item::Sale::kProductTypeEBook }

sub rServiceName {
    return BookPub::Tracker::Service::GetDefaultServiceName( service_id => shift->serviceID );
}

sub priceType {
    my $self = shift;
    if ( Common::RSApp::GetClientID == 318 ) {
        return 'agency';
    } else {
        return 'rrp';
    }
}

sub _processLine {
    my $self = shift;
    my $date = $self->_getByFieldName('dateBegin');

    if ( $date && $date =~ /Invoice Date/ ) {
        $self->{_endOfData} = 1;
    }

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

sub countryCode {
    my $self = shift;

    my $filename = $self->filename();

    $self->fail("Country code missing from filename")
      unless ( $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");
    }
}

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

    if ( $date && $date =~ /(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})/ ) {
        my ( $year, $month, $day ) = Add_Delta_YM( $1, $2, $3, 0, -1 );
        return sprintf( "%04d-%02d-%02d", $year, $month, $day );
    }
    if ( $date && $date =~ /(\d{1,2})\/(\d{1,2})\/(\d{4})/ ) {
        my $year = $3;
        my $month;
        my $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 );
        return sprintf( "%04d-%02d-%02d", $year, $month, $day );
    }
}

sub _dateNormalization { 'month' }

sub rRevenue {
    my $self  = shift;
    my $price = $self->_getByFieldName('rRevenue');

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

    return $price;
}

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 ne $revenueCurrency) && ($listPriceCurrency ne 'USD') ) {
        $listPriceCurrency = $revenueCurrency;
    }

    return $listPriceCurrency;
}

sub rListPrice {
    my $self              = shift;
    my $listPrice         = $self->_getByFieldName('rListPrice')         || 0;
    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 ne $revenueCurrency) && ($listPriceCurrency ne 'USD') && $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 rUnits {

    # We need to make sure that the sign of the units matches the sign of the revenue
    my $self    = shift;
    my $units   = $self->_getByFieldName('rUnits');
    my $revenue = $self->rRevenue;

    if ( ( $revenue < 0 && $units > 0 ) || ( $revenue > 0 && $units < 0 ) ) {
        $units *= -1;
    }

    return $units;
}

sub rUnitPrice {
    my $self = shift;

    return $self->rRevenue / ($self->rUnits || 1);
}

sub isFree {
    my $self = shift;

    my $revenue = $self->_getByFieldName("rRevenue") || 0;
    my $units   = $self->_getByFieldName("rUnits")   || 0;

    $revenue =~ s/^0\.0+$/0/g;

    return !$revenue && $units ? 'Y' : 'N';
}

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;
