#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2013 RoyaltyShare, Inc.   All Rights Reserved
#---------------------------------------------------------------

package RPS::Import::Caroline::v4;

use strict;

use Date::Calc qw(Days_in_Month Decode_Month);

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

use lib '/app/tools/rps/lib';
use RPS::Import::ServiceMap;

use base 'RPS::Import::Importer';

sub _fieldMap {
    my $self      = shift;
    my $version   = $self->_version;
    my %field_map = (
        4 => {

            # header
            dateBegin => 'B',    # A4

            # detail
            labelName        => 'K',
            upc              => 'S',
            artistName       => 'N',
            albumName        => 'O',
            priceLevel       => 'AQ',
            wholesalePrice   => 'AS',
            totalRevenue     => 'BB',
            productType      => 'AK',    # configuration
            serviceProductID => 'R',
        },
        17 => {

            # header
            dateBegin => 'A',

            # detail
            labelName        => 'I',
            upc              => 'S',
            artistName       => 'M',
            albumName        => 'N',
            priceLevel       => 'AJ',
            wholesalePrice   => 'AM',
            totalRevenue     => 'AX',
            productType      => 'AF',    # configuration
            serviceProductID => 'R',
        },
    );
    return $field_map{$version};
}

sub _unverifiedFieldMap {
    my $self      = shift;
    my $version   = $self->_version;
    my %field_map = (
        4 => {
            dateHeader => 'A',
            salesType  => 'Z',

            netUnits   => 'AY',
            netRevenue => 'BB',
        },
        17 => {
            dateHeader => 'A',
            salesType  => 'Z',

            netUnits   => 'AS',
            netRevenue => 'AX',
        },
    );
    return $field_map{$version};
}

sub _headerIdentifier { ( upc => qr/UPC(?: ID)?/ ) }

sub countryCode { "US" }

sub currencyCode { "USD" }

sub physical { 1 }

sub channel {
    my $self  = shift;
    my $stype = $self->_getByFieldName('salesType');
    if ( $stype =~ /^(11|53|29|41|56)$/i ) {
        return RPS::File::Sale::CHANNEL_RETAIL;
    } elsif ( $stype =~ /^54$/i ) {
        return RPS::File::Sale::CHANNEL_DIRECT;
    } elsif ( $stype =~ /^21$/i ) {
        return RPS::File::Sale::CHANNEL_MILITARY;
    }
    $self->fail("Unable to determine channel from '$stype'");
}

sub priceLevel {
    my $self  = shift;
    my $pt    = $self->_getByFieldName('priceLevel');
    my $stype = $self->_getByFieldName('salesType');

    # If salesType says promo, then this overrides the priceLevel column (FB2157)
    #
    return RPS::File::Sale::PLEVEL_PROMO if ( $stype =~ /^53$/ );

    if ( $pt =~ /^f$/i ) {
        return RPS::File::Sale::PLEVEL_FULL;
    } elsif ( $pt =~ /^m$/i ) {
        return RPS::File::Sale::PLEVEL_MID;
    } elsif ( $pt =~ /^b$/i ) {
        return RPS::File::Sale::PLEVEL_BUDGET;
    } elsif ( $pt =~ /^s$/i ) {
        return RPS::File::Sale::PLEVEL_FULL;
    } elsif ( $pt =~ /^x$/i ) {
        return RPS::File::Sale::PLEVEL_UNKNOWN;
    }
}

sub saleDates {
    my $self = shift;

    return ( $self->{_dateBegin}, $self->{_dateEnd} );

}

sub sales {
    my $self    = shift;
    my $units   = $self->_getByFieldName('netUnits');
    my $revenue = $self->_getByFieldName('netRevenue');
    return ( $revenue > 0 && $units ) ? abs($units) : 0;
}

sub salesRevenue {
    my $self    = shift;
    my $revenue = $self->_getByFieldName('netRevenue');
    return ( $revenue >= 0 ) ? $revenue : 0;
}

sub returns {
    my $self    = shift;
    my $units   = $self->_getByFieldName('netUnits');
    my $revenue = $self->_getByFieldName('netRevenue');
    return ( $revenue < 0 && $units ) ? abs($units) : 0;
}

sub returnsRevenue {
    my $self    = shift;
    my $revenue = $self->_getByFieldName('netRevenue');
    return ( $revenue < 0 ) ? abs($revenue) : 0;
}

sub free {
    my $self         = shift;
    my $totalRevenue = $self->_getByFieldName('totalRevenue');
    my $sales        = $self->_getByFieldName('sales');
    my $returns      = $self->_getByFieldName('returns');
    return 1 if ( $totalRevenue == 0 && ( $sales != 0 || $returns != 0 ) );
}

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

    if ( $type =~ /^lp$/i ) {
        return RPS::File::Sale::TYPE_LP;
    } elsif ( $type =~ /^(cd|co)$/i ) {
        return RPS::File::Sale::TYPE_CD;
    } elsif ( $type =~ /^cf$/i ) {
        return RPS::File::Sale::TYPE_DBL_CD;
    } elsif ( $type =~ /^dv$/i ) {
        return RPS::File::Sale::TYPE_DVD;
    } elsif ( $type =~ /^st$/i ) {
        return RPS::File::Sale::TYPE_LP5;
    } elsif ( $type =~ /^(dx|dz)$/i ) {
        return RPS::File::Sale::TYPE_DVD_CD_SET;
    } elsif ( $type =~ /^(s|s5)$/i ) {
        return RPS::File::Sale::TYPE_CD_SIN;
    } elsif ( $type =~ /^ct$/i ) {
        return RPS::File::Sale::TYPE_CASS;
    }
    $self->fail("Unable to determine product type from '$type'");
}

sub _processSheet {
    my $self     = shift;
    my $sheet    = shift;
    my $sheetnum = shift;

    if ( $self->{sheetname} =~ /physical/i ) {

        my $dateBegin;
        my $dateEnd;
        my $linenum = 0;

        foreach my $line (@$sheet) {
            $self->{line} = $line;

            my $dheader = $self->_getByFieldName('dateHeader');

            my $dt = $self->_getByFieldName('dateBegin');

            if ( $dheader =~ /^dates$/i ) {
                my $months = "jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec";

                if ( $dt =~ /\((\w{3})\s*(\d{1,2})\) to .*\((\w{3})\s*(\d{1,2})\)/ )    # ... (MMM YY) to ... (MMM YY) ...
                {
                    my ( $sMonth, $sYear, $eMonth, $eYear ) = ( $1, $2, $3, $4 );

                    $dateBegin = sprintf( "%04d-%02d-%02d", ( $sYear + 2000 ), $self->_getMonth($sMonth), 1 );

                    my $_month = $self->_getMonth($eMonth);
                    my $_year  = $eYear + 2000;
                    $dateEnd = sprintf( "%04d-%02d-%02d", $_year, $_month, Days_in_Month( $_year, $_month ) );

                    $self->{_dateBegin} = $dateBegin;
                    $self->{_dateEnd}   = $dateEnd;

                    last;
                } elsif ( $dt =~ /($months) (\d{1,2}).* to .*($months) (\d{1,2})/i )    # ... MMM YY ... to ... MMM YY ...
                {
                    my ( $sMonth, $sYear, $eMonth, $eYear ) = ( $1, $2, $3, $4 );

                    $dateBegin = sprintf( "%04d-%02d-%02d", ( $sYear + 2000 ), $self->_getMonth($sMonth), 1 );

                    my $_month = $self->_getMonth($eMonth);
                    my $_year  = $eYear + 2000;
                    $dateEnd = sprintf( "%04d-%02d-%02d", $_year, $_month, Days_in_Month( $_year, $_month ) );

                    $self->{_dateBegin} = $dateBegin;
                    $self->{_dateEnd}   = $dateEnd;

                    last;
                }
            } elsif ( $dheader =~ /Period \(ID\) = (\d{4})(\d{2})/i )    # YYYYMM
            {
                $dateBegin = sprintf( "%04d-%02d-01", $1, $2 );
                $dateEnd = sprintf( "%04d-%02d-%02d", $1, $2, Days_in_Month( $1, $2 ) );
                $self->{_dateBegin} = $dateBegin;
                $self->{_dateEnd}   = $dateEnd;
                last;
            }

            $linenum++;
        }

        return $self->SUPER::_processSheet( $sheet, $sheetnum );
    }

}

sub _getMonth {
    my $self  = shift;
    my $month = shift;

    my %months = (
        'JAN' => '01',
        'FEB' => '02',
        'MAR' => '03',
        'APR' => '04',
        'MAY' => '05',
        'JUN' => '06',
        'JUL' => '07',
        'AUG' => '08',
        'SEP' => '09',
        'OCT' => '10',
        'NOV' => '11',
        'DEC' => '12',
    );

    return $months{ uc $month };
}

sub _isValidSaleRecord {
    my $self    = shift;
    my $units   = $self->_getByFieldName('netUnits');
    my $revenue = $self->_getByFieldName('netRevenue');

    # Check here for zero units and either positive or negative revenue
    # and halt
    if ( ( $units == 0 && $revenue != 0 ) && $self->albumName ) {
        $self->fail("Zero units with non-zero revenue");
    }

    # The line is valid if it has sales or returns, and has an album title
    #
    return ( ( $self->sales != 0 || $self->returns != 0 ) && $self->albumName );
}

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