package BookPub::Import::Importer::BakerAndTaylor::Version5;

use strict;
use Date::Calc qw(Add_Delta_Days);

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

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

sub _useIsSaleRec { 1 }

sub _fieldMap {
    {
        # Header
        rPriceType   => 'G',
        currencyCode => 'H',

        # Detail
        serviceProductID     => 'F',
        dateBegin            => 'E',
        isbn                 => 'K',
        rProductType         => 'G',
        rFormat              => 'G',
        rTitle               => 'N',
        rAuthor              => 'O',
        rUnits               => 'U',
        rSales               => 'S',
        rReturns             => 'T',
        countryCode          => 'Y',
        rListPrice           => 'Z',
        rListPriceCurrency   => 'AB',
        rDiscount            => 'AC',
        rRevenue             => 'AP',
        rComments            => 'G',
        rInstitution         => 'D',
        priceTypeQualifierID => 'G',
    };
}

# There's a priceType in the header and also one on each line, we'll use the line
# type if there, otherwise the header value
sub _unverifiedFieldMap {
    { rPriceTypeLine => 'AA', };
}

#   This field map will only be used for the tax tab (if there is one)
#
my %taxFieldMap = (

    # For data
    rState      => 3,
    rPostalCode => 7,
    rImprint    => 32,

    # For verification
    isbn   => 25,
    rUnits => 33,

    #rListPrice      => 34,
);

my %taxData;
my $foundTaxTab = 0;

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

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

    my $sheetnum = 0;

    foreach my $sheet ( @{ $args{sheets} } ) {
        my $sheetname = $args{sheet_names}->[$sheetnum];
        $sheetnum++;

        # We need to go through the tax tab and store some of that data in a hash
        # so that we can access it while processing the Sales tab.
        if ( $sheetname eq 'Tax' ) {

            # Set the flag, so that we know to do all of the extra stuff for files that
            # have this extra tab.
            $foundTaxTab = 1;
            my $linenum     = 0;
            my $foundHeader = 0;
            foreach my $line (@$sheet) {

                $linenum++;

                if ( $line->[0] eq 'Publisher' ) {
                    $foundHeader = 1;
                    next;
                } elsif ( $foundHeader == 0 ) {
                    next;
                }

                # We've encountered tax tabs that aren't populated correctly.
                # If we notice that, we'll just pretend we never saw the tax tab.
                if ( $line->[ $taxFieldMap{rUnits} ] eq '#REF!' ) {
                    $foundTaxTab = 0;
                    last;
                }

                # Grab the data and store it
                $taxData{$linenum}{rState}      = $line->[ $taxFieldMap{rState} ];
                $taxData{$linenum}{rPostalCode} = $line->[ $taxFieldMap{rPostalCode} ];
                $taxData{$linenum}{rImprint}    = $line->[ $taxFieldMap{rImprint} ];

                $taxData{$linenum}{isbn}   = $line->[ $taxFieldMap{isbn} ];
                $taxData{$linenum}{rUnits} = $line->[ $taxFieldMap{rUnits} ];

                #$taxData{$linenum}{rListPrice}  = $line->[$taxFieldMap{rListPrice}];
            }

        }
    }

}

sub rServiceName { "Baker and Taylor" }

sub priceType {
    my $self = shift;

    my $typeFromLine   = $self->_getByFieldName('rPriceTypeLine');
    my $typeFromHeader = $self->_getByFieldName('rPriceType');
    if ($typeFromLine) {
        return $self->_priceTypePicker($typeFromLine);
    } elsif ($typeFromHeader) {
        return $self->_priceTypePicker($typeFromHeader);
    }
}

sub priceTypeQualifierID {
    my $self = shift;

    my $type = $self->_getByFieldName('priceTypeQualifierID') || '';
    if ( $type =~ /^Axis-(?:Library|Academic)\s?(?:Intl)?$/i ) {    # Library
        return BookPub::DB::Item::PriceTypeQualifier::kCorporate;
    } elsif ( $type =~ /^Axis-(?:Education|School)?$/i ) {          # School Library
        return BookPub::DB::Item::PriceTypeQualifier::kSchoolLibrary;
    } elsif ( $type =~ /^(?:Blio|Epub|pdf)-Retail$/i ) {
        return;
    }

    $self->fail("Unable to determine price type qualifier for '$type'");
}

sub _priceTypePicker {
    my $self = shift;
    my $type = shift;

    if ( lc($type) eq "01" ) {
        return 'rrp';
    } elsif ( lc($type) eq "41" ) {
        return 'agency';
    }
    return $self->fail( "Invalid priceType: " . $type );
}

sub rProductType {
    my $self = shift;
    my $type = $self->_getByFieldName('rProductType');
    if (   $type eq 'Axis-Education'
        || $type eq 'Axis-Library'
        || $type eq 'Axis-Library Intl'
        || $type eq 'Axis-Academic'
        || $type eq 'Axis-Academic Intl'
        || $type eq 'Axis-School'
        || $type eq 'Blio-Retail'
        || $type eq 'Blio-Library'
        || $type eq 'PDF'
        || $type eq 'PDF-Retail'
        || $type eq 'Retail'
        || $type eq 'Epub-Retail'
        || $type eq 'Epub' ) {
        return BookPub::DB::Item::Sale::kProductTypeEBook;
    }
    if ( $type eq 'Find' ) {
        return BookPub::DB::Item::Sale::kProductTypeAudioBook;
    }

    $self->fail("No product type set for $type");

}

sub formatType {
    my $self   = shift;
    my $format = $self->_getByFieldName('rFormat');

    if (   $format eq 'Axis-Education'
        || $format eq 'Axis-Library'
        || $format eq 'Axis-Library Intl'
        || $format eq 'Axis-Academic'
        || $format eq 'Axis-Academic Intl'
        || $format eq 'Axis-School'
        || $format eq 'Blio-Retail'
        || $format eq 'Blio-Library'
        || $format eq 'Retail' ) {
        return BookPub::DB::Item::Sale::kFormatTypeUnknownEBook;
    }
    if (   $format eq 'Epub'
        || $format eq 'Epub-Retail' ) {
        return BookPub::DB::Item::Sale::kFormatTypeEPub;
    }
    if (   $format eq 'PDF'
        || $format eq 'PDF-Retail' ) {
        return BookPub::DB::Item::Sale::kFormatTypePDF;
    }
    if ( $format eq 'Find' ) {
        return BookPub::DB::Item::Sale::kFormatTypeAudioUnknown;
    }

    $self->fail("No format type set for $format");

    return $format;
}

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

    return $countryCode;
}

sub rState {
    my $self = shift;
    my $state;

    if ( $foundTaxTab == 1 ) {
        $state = $taxData{ $self->linenum }{rState};
    }

    return $state;
}

sub rPostalCode {
    my $self = shift;
    my $postalCode;

    if ( $foundTaxTab == 1 ) {
        $postalCode = $taxData{ $self->linenum }{rPostalCode};

        # The occasional letter or underscore has been showing up in the zip codes.
        # So, let's get rid of anything that's not a number (but only if country code is US!).
        if ( $self->{_countryCode} eq 'US' ) {

            # Actually, let's leave dashes in too.  This should only affect letters and underscores.
            $postalCode =~ s/[a-zA-Z_]//g;
        }
    }

    return $postalCode;
}

sub rImprint {
    my $self = shift;
    my $imprint;

    if ( $foundTaxTab == 1 ) {
        $imprint = $taxData{ $self->linenum }{rImprint};
    }

    return $imprint;
}

sub isbn {
    my $self = shift;
    my $isbn = $self->SUPER::isbn() || return;

    if ( $foundTaxTab == 1 ) {
        my $linenum = $self->linenum;
        my $taxIsbn = $taxData{$linenum}{isbn};

        if ( $isbn ne $taxIsbn ) {
            $self->fail("ISBNs for line $linenum do not match ($isbn != $taxIsbn).");
            return undef;
        }
    }

    return $isbn;
}

sub rUnits {
    my $self = shift;
    my $rUnits = $self->SUPER::rUnits() || return;

    if ( $foundTaxTab == 1 ) {
        my $linenum  = $self->linenum;
        my $taxUnits = $taxData{ $self->linenum }{rUnits};

        if ( $rUnits != $taxUnits ) {
            $self->fail("Unit values for line $linenum do not match ($rUnits != $taxUnits).");
            return undef;
        }
    }

    return $rUnits;
}

sub isFree {
    my $self    = shift;
    my $price   = $self->_getByFieldName('rListPrice');
    my $revenue = $self->_getByFieldName('rRevenue');
    return ( $price && $revenue ) ? 'N' : 'Y';
}

sub _processHeader {
    my $self         = shift;
    my $currencyCode = $self->_getByFieldName('currencyCode');

    if ( $self->{_firstHeaderFound} ) {
        $self->{_currencyCode} = $self->_getByFieldName('currencyCode');
        $self->{_priceType}    = $self->_getByFieldName('rPriceType');

        $self->{_firstHeaderFound} = undef;

    } elsif ( $currencyCode && $currencyCode eq 'Reporting currency' ) {
        $self->{_firstHeaderFound} = 1;
    }

    # Check to ensure we found the first header
    if ( $self->_isHeader() ) {
        $self->fail("No currency code found in the header") unless ( $self->{_currencyCode} );
        $self->fail("No price type found in the header")    unless ( $self->{_priceType} );
    }
}

sub _dateFormat { [ 'excel', 'iso' ] }

sub _isSaleRec {
    my $self = shift;

    if ( $self->_getByFieldName('rRevenue') eq '-' ) {
        return undef;
    }

    # Need to ignore the total line at the end.
    if (   !$self->_getByFieldName('serviceProductID')
        && !$self->_getByFieldName('dateBegin')
        && !$self->_getByFieldName('isbn')
        && !$self->_getByFieldName('rProductType')
        && !$self->_getByFieldName('rTitle')
        && !$self->_getByFieldName('rAuthor')
        && !$self->_getByFieldName('countryCode')
        && !$self->_getByFieldName('rListPriceCurrency') ) {
        return undef;
    }

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

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