#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# 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.
###
