package BookPub::Import::Importer::BarnesNoble::Version6;

use strict;
use Data::Dumper;

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

use lib '/app/tools/sale_import/lib/';
use Import::ValidationError;

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

sub _headerIdentifier { ( rTitle => 'Title' ) }

sub _fieldMap {
    {
        currencyCode       => 'Y',
        countryCode        => 'M',
        dateBegin          => 'J',
        rIsbn13            => 'C',
        rTitle             => 'D',
        rAuthor            => 'E',
        rSales             => 'U',
        rReturns           => 'U',
        rListPrice         => 'Q',
        rListPriceCurrency => 'AB',
        rPurchasePrice     => 'R',
        rDiscount          => 'V',
        rUnitPrice         => 'Z',
        rRevenue           => 'AA',
    };
}

sub _unverifiedFieldMap {
    {
        eGiftDateBegin => 'K',
        orderType      => 'I',
    };
}

sub productType { BookPub::DB::Item::Sale::kProductTypeEBook }

sub purchaseType { BookPub::DB::Item::Sale::kPurchaseTypeDownload }

sub _getDateBegin {
    my $self = shift;

    # We'll use the eGift Date if that column is populated.
    my $date = $self->_getByFieldName('eGiftDateBegin');

    if ( !$date ) {
        $date = $self->_getByFieldName('dateBegin');
    }

    return $date;
}

sub rDiscount {
    my $self = shift;

    my $discount = $self->_getByFieldName('rDiscount');
    $discount =~ s/%//;
    $discount = 100 - $discount;

    return $discount;
}

sub countryCode {
    my $self = shift;

    # 1 = US
    my $countryCode = $self->_getByFieldName('countryCode');
    if ( $countryCode == 1 ) {
        $countryCode = 'US';
    }

    return $countryCode;
}

sub priceType {
    my $self = shift;
    my $priceType;
    if ( $self->isMacmillan ) {
        my $country = $self->countryCode;
        if ( $country eq 'US' || $country eq 'CA' ) {
            $priceType = 'agency';
        } else {
            $priceType = 'rrp';
        }
    } else {
        $priceType = $self->{_priceType};
    }

    return $priceType;
}

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

    # For Macmillan, RLPG, and Wiley, we want the list price currency to match the revenue currency.
    # We'll also be converting the list price.
    if ( $self->isMacmillan || $self->isWiley || $self->isRLPG ) {
        $listPriceCurrency = $revenueCurrency;
    }

    return $listPriceCurrency;
}

sub listPrice {
    my $self = shift;

    my $listPrice         = $self->SUPER::listPrice;
    my $listPriceCurrency = uc( $self->_getByFieldName('rListPriceCurrency') );
    my $revenueCurrency   = $self->currencyCode;

    Log->debug("Initial list price: $listPrice");

    # Macmillan-specific handling (now using _some_ of this for Wiley and RLPG too)
    if ( $self->isMacmillan || $self->isWiley || $self->isRLPG ) {

        Log->debug( "Macmillan: [" . $self->linenum . "] Listprice: $listPrice" );
        Log->debug( "Macmillan: [" . $self->linenum . "] Revenue: " . $self->revenue );
        Log->debug( "Macmillan: [" . $self->linenum . "] List Price Currency: $listPriceCurrency" );

        # To address import issue:
        # http://tools.royaltyshare.com/fogbugz/default.php?17318 - Kilna
        if ( !$listPrice && $self->revenue && $self->isMacmillan ) {
            Log->debug( "Macmillan: [" . $self->linenum . "] Setting list price to purchase price: " . $self->rPurchasePrice );
            $listPrice = $self->rPurchasePrice;
        }

        # Override list prices with value calculated from discount if the currency does not matcn the revenue currency
        if ( $listPriceCurrency && $listPriceCurrency ne $revenueCurrency ) {
            Log->debug( "Macmillan: [" . $self->linenum . "] Overriding list price based on discount" );
            my $discountedPrice = ( 1 - ( $self->rDiscount / 100 ) ) * $listPrice;
            my $unitPrice       = $self->revenue / $self->units;
            my $conversionRate  = $unitPrice / $discountedPrice;
            $listPrice *= $conversionRate;
            Log->debug( "Macmillan: [" . $self->linenum . "] New list price is $listPrice" );
        }
    }

    Log->debug("Final list price: $listPrice");

    return $listPrice;
}

sub rListPrice {
    my $self = shift;

    my $value = $self->SUPER::rListPrice;
    $value =~ s/,//g;

    return $value;
}

sub rPurchasePrice {
    my $self = shift;

    my $value = $self->SUPER::rPurchasePrice;
    $value =~ s/,//g;

    return $value;
}

sub rRevenue {
    my $self = shift;

    my $revenue = $self->SUPER::rRevenue();

    $revenue =~ s/,//g;

    my $units = $self->units || 0;

    if ( $revenue > 0 && $units < 0 ) {
        $self->fail("Positive revenue found with negative units");
        return undef;
    }

    if ( $revenue < 0 && $units > 0 ) {
        $self->fail("Negative revenue found with positive units");
        return undef;
    }

    return $revenue;
}

sub rSales {
    my $self = shift;
    my $sales;
    my $orderType = $self->_getByFieldName('orderType');

    if ( $orderType eq 'INV' ) {
        $sales = $self->SUPER::rSales();
        $sales =~ s/,//g;

        if ( $sales < 0 ) {
            $self->fail("Sales cannot be negative");
            return undef;
        }
    }

    return $sales;
}

sub rReturns {
    my $self = shift;
    my $returns;
    my $orderType = $self->_getByFieldName('orderType');

    if ( $orderType eq 'CRE' ) {
        $returns = $self->SUPER::rReturns();
        $returns =~ s/,//g;

        # In this file format, returns are a negative number.
        # However, returns are stored as a postive number in our database,
        # so we have to flip the sign.
        if ( $returns > 0 ) {
            $self->fail("Returns cannot be positive");
            return undef;
        } else {
            $returns *= -1;
        }
    }

    return $returns;
}

sub units {
    my $self = shift;

    my $sales = $self->rSales || 0;

    my $returns = $self->rReturns || 0;

    return $sales - $returns;
}

sub rTitle {
    my $self = shift;

    my $title = $self->SUPER::rTitle();
    my $subtitle;
    ( $title, $subtitle ) = BookPub::Import::Importer::ParseTitleAndSubtitle($title);

    return $title;
}

sub rSubtitle {
    my $self = shift;

    my $title = $self->SUPER::rTitle();
    my $subtitle;
    ( $title, $subtitle ) = BookPub::Import::Importer::ParseTitleAndSubtitle($title);

    return $subtitle;
}

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

    Log->info("Starting _preProcess");
    $self->SUPER::_preProcess(%args);

    # going to make our best guess as to whether this file contains agency model transactions.
    # we do that by looking at all transaction and if more than 75% of them return at least 65%
    # of the revenue back to the publisher, we'll assume (and i mean assume) they have an agency
    # agreement in place. Currently, agency deals are 70% of retail price and RRP typically 50%
    # of suggested retail. for historical reference, we started doing this because on 12/2/2011,
    # b & n stopped populating the "Order Type" column.

    my $isAgency;
    my $recs;
    my $agencies;
    my $priceType;

    # For Wiley and Hyperion, this file is always RRP.  Disney and Hachette are always Agency.
    my $filename = $self->filename();
    my $clientID = Common::RSApp::GetClientID();

    if ( $clientID == 324 ) {
        $priceType = 'rrp';
    } elsif ( $clientID == 347 ) {
        $priceType = 'rrp';
    } elsif ( $clientID == 308 ) {
        $priceType = 'agency';
    } elsif ( $clientID == 330 ) {
        $priceType = 'agency';
    } else {
        foreach my $sheet ( @{ $args{sheets} } ) {
            foreach my $line (@$sheet) {

                # Since we're at the preProcess stage, it seems we have to reference rows by number.
                if ( $line->[2] || $line->[3] ) {
                    my ($unitPrice) = ( $line->[26] =~ m/^\s*-*\$*(\d*\.*\d+)\s*$/ );
                    my ($listPrice) = ( $line->[17] =~ m/^\s*-*\$*(\d*\.*\d+)\s*$/ );

                    if ( $listPrice && $listPrice != 0 ) {
                        $recs++;
                        $agencies++ if ( $unitPrice / $listPrice >= .65 );
                    }
                }
            }
        }

        $isAgency = ( $agencies / $recs ) >= .75;

        if ( $isAgency == 1 ) {
            $priceType = 'agency';
        } else {
            $priceType = 'rrp';
        }
    }

    $self->{_priceType} = $priceType;
}

sub isMacmillan {
    Log->debug( "Client ID: " . Common::RSApp::GetClientID() );
    return ( Common::RSApp::GetClientID() == 318 ) ? 1 : 0;
}

sub isWiley {
    Log->debug( "Client ID: " . Common::RSApp::GetClientID() );
    return ( Common::RSApp::GetClientID() == 324 ) ? 1 : 0;
}

sub isRLPG {
    Log->debug( "Client ID: " . Common::RSApp::GetClientID() );
    return ( Common::RSApp::GetClientID() == 346 ) ? 1 : 0;
}

1;
