package BookPub::Import::Importer::Macquarie;

use strict;

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

sub _fieldMap {
    my $self = shift;

    my %fieldMap = (
        2 => {
            countryCode          => 'V',
            rIsbn13              => 'Y',
            rTitle               => 'AE',
            rComments            => 'B',
            rSales               => 'I',
            rReturns             => 'I',
            rListPrice           => 'X',
            rPurchasePrice       => 'W',
            rRevenue             => 'X',
            rDuration            => 'AA',
            rPromoCode           => 'M',
            rTransactionCategory => 'B',
        },
        3 => {
            rTitle         => 'AC',
            rIsbn13        => 'W',
            countryCode    => 'T',
            rReturns       => 'G',
            rSales         => 'G',
            rListPrice     => 'V',
            rPurchasePrice => 'U',
            rRevenue       => 'V',
            rPromoCode     => 'K',
            rModel         => 'A',
            rComments      => 'A',
        },
    );

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

sub _headerIdentifier {
    my $self = shift;

    my %headerMap = (
        2 => {
            rSales => 'status',
        },
        3 => {
            rComments => 'Subscription Type Purchased',
        },
    );

    return %{ $headerMap{ $self->_version } };
}

sub purchaseType           { BookPub::DB::Item::Sale::kPurchaseTypeSubscriptionDL }
sub productType            { BookPub::DB::Item::Sale::kProductTypeEBook }
sub rProductType           { BookPub::DB::Item::Sale::kProductTypeEBook }
sub formatType             { BookPub::DB::Item::Sale::kFormatTypeHTML }
sub rFormat                { BookPub::DB::Item::Sale::kFormatTypeHTML }
sub priceType              { 'rrp' }
sub currencyCode           { 'AUD' }
sub rListPriceCurrency     { 'AUD' }
sub rPurchasePriceCurrency { 'AUD' }
sub _useIsSaleRec          { 1 }

# We're taking column mapped to 'rComments' and putting it in the comments field to use as a SAN on
# the production system.  This is an array of all permissible values.  We'll
# check that in the rComments method
my @valid_sans_array = qw( data_licence
    data_license
    individual_user
    institution
    public_library
    school
    school_university
    trial
    library
    professional-editor
);

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

# map the SAN array to a hash and check the value against it.  Fail if not found
sub rComments {
    my $self = shift;

    my $san        = $self->_getByFieldName('rComments') || '';
    my %valid_sans = map { $_ => 1 } @valid_sans_array;

    unless ( exists $valid_sans{lc $san} ) {
        $self->fail( "Invalid SAN: " . $san );
    }

    return $san;
}

sub _isSaleRec {
    my $self  = shift;

    my $sales = $self->_getByFieldName('rSales') || '';
    return if $self->_isCancelledDeclined($sales);

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

sub isFree {
    my $self  = shift;

    my $value = $self->_getByFieldName('rSales');
    return $value eq "na" ? 'Y' : 'N';
}

sub units {
    my $self    = shift;

    my $sales   = $self->rSales;
    my $returns = $self->rReturns;

    return $sales - $returns;
}

sub rTaxUnitPrice {
    my $self = shift;

    my $purchasePrice = $self->SUPER::rPurchasePrice() || 0;
    my $listPrice     = $self->SUPER::rListPrice()     || 0;
    my $sales         = $self->SUPER::rSales()         || 0;
    my $tax           = $purchasePrice - $listPrice;

    $tax *= -1 if ($self->_isRefund($sales));

    return $purchasePrice =~ /none/i ? undef : $tax;
}

sub rTaxAmount {
    my $self = shift;

    my %mapRules = (
        2 => $self->rTaxUnitPrice,
        3 => $self->rTaxUnitPrice,
    );

    if ( exists $mapRules{ $self->_version } ) {
        return $mapRules{ $self->_version };
    }

    return;
}

sub rPurchasePrice {
    my $self = shift;

    my $purchasePrice = $self->SUPER::rPurchasePrice() || 0;
    my $listPrice     = $self->SUPER::rListPrice()     || 0;

    return $purchasePrice =~ /none/i ? $listPrice : $purchasePrice;
}

sub rRevenue {
    my $self = shift;

    my $revenue = $self->SUPER::rRevenue() || 0;
    my $sales   = $self->SUPER::rSales()   || 0;

    return $self->_isRefund($sales) ? -1 * $revenue : $revenue;
}

sub rSales {
    my $self = shift;

    my $sales = $self->SUPER::rSales();
    return $self->_isRefund($sales) ? 0 : 1;
}

sub rReturns {
    my $self = shift;

    my $returns = $self->SUPER::rReturns();
    return $self->_isRefund($returns) ? 1 : 0;
}

sub _getDateBegin {
    my $self = shift;

    if ( $self->filename =~ /[_-](\d{4})(\d{2})(\d{2})?\./ ) {
        return "$1-$2-01";
    }

    $self->fail( "Unable to determine date from filename: " . $self->filename );
}

sub _getDateEnd {
    my $self = shift;

    my $date = new Common::Date(
        date => $self->_getDateBegin,
        type => $self->_dateFormat,
    );

    return $date->monthEnd();
}

sub _isRefund {
    my ($self, $status) = @_;

    my %regexMap = (
        2 => qr/refund(ed)?|credited/i,
        3 => qr/refund(ed)?/i,
    );

    return defined $status && $status =~ $regexMap{ $self->_version } ? 1 : 0;
}

sub _isCancelledDeclined {
    my $self   = shift;
    my $status = shift || '';

    return $status =~ /cancelled|payment.*declined/i ? 1 : 0;
}

1;
