package RPS::Import::ADAPhysical::v6;

use strict;

use lib '/app/tools/common/lib';
use Common::Util qw(normalize_date normalize_upc);
use Common::Country;
use Date::Calc qw(Days_in_Month);
use Data::Dumper;

use lib '/app/tools/data_classes/lib';

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

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

use constant kDataNotFound => -1;

sub _fieldMap {
    {
        'statement summary' => {
            date_row => 3,
            date_col => 1,
        },

        'physical sales' => {
            label          => 0,     # A
            configuration  => 7,     # H
            artistName     => 3,     # D
            catalogID      => 2,     # C
            upc            => 8,     # I
            albumName      => 4,     # E
            country        => 12,    # M
            wholesalePrice => 13,    # N
            distFee        => 22,    # W
            returnFee      => 23,    # X

            sales        => 14,      # O
            returns      => 15,      # P
            netUnits     => 16,      # Q
            totalRevenue => 24,      # Y
        },
    };
}

my %productTypeMap = (
    '1cd'              => RPS::File::Sale::TYPE_CD,
    '2cd'              => RPS::File::Sale::TYPE_CD,
    'single (10")'     => RPS::File::Sale::TYPE_LP5,
    '12" vinyl single' => RPS::File::Sale::TYPE_LP5,
    '7"'               => RPS::File::Sale::TYPE_LP5,
    '12" vinyl'        => RPS::File::Sale::TYPE_LP,
    'cd'               => RPS::File::Sale::TYPE_CD,
    '1cd + 1dvd'       => RPS::File::Sale::TYPE_DVD_CD_SET,
    '12" vinyl x 2'    => RPS::File::Sale::TYPE_LP,
    'lp'               => RPS::File::Sale::TYPE_LP,           # FB 10795
    '1lp'              => RPS::File::Sale::TYPE_LP,           # FB 10795
);

#
# Private methods
#

sub _importLines {
    my $self     = shift;
    my %args     = @_;
    my $fileObj  = $args{file};
    my $version  = $args{file}->VersionNum();
    my $fileName = $args{file}->OrigFileName();

    my $offsets = $self->_fieldMap;

    my $sheet_count = 0;
    my ( $linenum, $serviceID );

    return undef unless ( defined $args{sheets} && defined $version );

    my $sheet_names = $args{sheet_names};

    my $dateBegin;
    my $dateEnd;

    my $dateField;

    #----------------------------------------------------
    # Extract the date information from the summary sheet
    #----------------------------------------------------

    # Assume that the first sheet is the summary sheet
    #
    my $sheet = @{ $args{sheets} }[0];

    if ( $sheet_count == 0 ) {

        # The row/column offsets can be skewed if there are blank columns (left)
        # and/or rows (top) in the sales file.  Scan the first 10 rows to see
        # if we can find the date information.
        #
        my $dateFound;
        my $row = 0;
        while ( !$dateFound && $row < 10 ) {
            my $data = $offsets->{'statement summary'};

            # Get the date information from the top of each sheet
            #
            my $dateRow = $row;
            my $dateCol = $data->{date_col};

            $dateField = $sheet->[$dateRow][$dateCol];
            if ( !$dateField ) {

                # If sheet has a blank leftmost column, then the column offset will be off by 1
                #
                $dateField = $sheet->[$dateRow][ $dateCol - 1 ];
            }

            # Period: DD/MM/YYYY - DD/MM/YYYY
            #         $1 $2  $3    $4 $5  $6
            if ( $dateField =~ m/Period: (\d{1,2})\/(\d{1,2})\/(\d{4}) . (\d{1,2})\/(\d{1,2})\/(\d{4})/ ) {

                # FB4918: Use the end date to determine the sales period
                #
                my ( $eDay, $eMonth, $eYear ) = ( $4, $5, $6 );
                $dateBegin = join( "-", $eYear, sprintf( "%02d", $eMonth ), "01" );
                $dateEnd = join( "-", $eYear, sprintf( "%02d", $eMonth ), Days_in_Month( $eYear, $eMonth ) );

                ( $dateBegin, $dateEnd ) = $self->_getDates( date_begin => $dateBegin, date_end => $dateEnd );

                $dateFound = 1;
            }

            $row++;
        }
    }

    #-------------------------
    # Process the detail sheet
    #-------------------------
    $sheet_count = 0;
    foreach my $sheet ( @{ $args{sheets} } ) {

        my $sheetName = $sheet_names->[$sheet_count];

        my $sheetIndex = lc $sheetName;

        if ( $sheetIndex ne 'physical sales' ) {
            $sheet_count++;
            next;
        }

        my $data = $offsets->{$sheetIndex};

        $linenum = 1;
        foreach my $line ( @{$sheet} ) {

            my $sn       = $sheet_count + 1;
            my $lineInfo = "Sheet $sn, line $linenum";

            my $cfg = $line->[ $data->{configuration} ];

            # Defaulting config to CD if blank (FB8937)
            if ( !$cfg ) {
                $cfg = 'cd';
            }

            my $catalogNumber = $line->[ $data->{catalogID} ];
            my $label         = $line->[ $data->{label} ];
            my $upc           = $line->[ $data->{upc} ];
            my $artist        = $line->[ $data->{artistName} ];
            my $title         = $line->[ $data->{albumName} ];
            my $wholesale     = $line->[ $data->{wholesalePrice} ];
            my $country       = $line->[ $data->{country} ];

            my $netUnits     = $line->[ $data->{netUnits} ];
            my $totalRevenue = $line->[ $data->{totalRevenue} ];

            # Use the net units and revenue for the sales and returns data
            #
            my $sales          = $line->[ $data->{sales} ];
            my $salesRevenue   = ( $totalRevenue > 0 ) ? $totalRevenue : 0;
            my $returns        = $line->[ $data->{returns} ];
            my $returnsRevenue = ( $totalRevenue < 0 ) ? $totalRevenue : 0;

            if ( $sales < 0 ) {
                $returns += $sales;
                $sales = 0;
            }

            # Accept lines with sales or returns with revenue.  Also accept lines with
            # revenue but no sale or return units (these will error out, which is what we want).
            #
            if (   ( $sales || $returns || $totalRevenue )
                && $cfg !~ m/format\/config/i
                && ( $artist || $title || $upc ) ) {

                my $countryCode;
                if ( my $obj = Common::Country->Get($country) ) {
                    $countryCode = $obj->alpha2();
                } else {
                    $self->errstr("Unknown country '$country' in line $linenum");
                    return undef;
                }

                my $productType = $productTypeMap{ lc $cfg };
                if ( !$productType ) {
                    print STDERR "Can't determine product type from '$cfg' in line $linenum";
                    $self->errstr("Can't determine product type from '$cfg' in line $linenum");
                    return undef;
                }

                my $sale = RPS::Import::SaleRec->new();

                if ($returns) {
                    $sale->returns( abs($returns) );
                    $sale->returnsRevenue( abs($returnsRevenue) );
                }
                if ($sales) {
                    $sale->sales($sales);
                    $sale->salesRevenue($salesRevenue);
                }

                $sale->totalRevenue($totalRevenue);

                my $free     = 0;
                my $netUnits = $sales + $returns;

                if ( $netUnits != 0 && $totalRevenue == 0 ) {
                    $free = 1;
                }

                $sale->free($free);

                $sale->wholesalePrice($wholesale);
                $sale->productType($productType);
                $sale->dateBegin($dateBegin);
                $sale->dateEnd($dateEnd);
                $sale->labelName($label);
                $sale->albumName($title);
                $sale->serviceProductID($catalogNumber);

                $sale->upc( Common::Util::normalize_upc($upc) ) if ($upc);

                $sale->artistName($artist);

                $sale->channel(RPS::File::Sale::CHANNEL_RETAIL);
                $sale->priceLevel(RPS::File::Sale::PLEVEL_FULL);
                $sale->countryCode($countryCode);
                $sale->currencyCode('GBP');

                $sale->lineNum($linenum);

                $self->_insertSale( sale => $sale );
            }

            #            else { print STDERR "skip sheet($sheetIndex) l($linenum) ar($artist) title($title) "
            #                   ." s($sales), r($returns) sR($salesRevenue) rR($returnsRevenue) tR($totalRevenue)\n"; }
            $linenum++;
        }
        $sheet_count++;
    }

    return $linenum;
}

sub _validateTotalSum {
    my ( $self, $saleRec ) = @_;
}

sub _validateReturnTotalSum {
    my ( $self, $saleRec ) = @_;
}

sub _validateSaleTotalSum {
    my ( $self, $saleRec ) = @_;
}

# _getDates: helper method to process US or UK formatted dates.
#
# The end date is checked to see if it's a US or UK-formatted date, with
# the assumption that the day will be be greater than 12 (most likely
# between 28-31). The begin date determines the reporting period, which
# will span one month regardless of the end date specified in the file.
#
sub _getDates {
    my $self = shift;
    my %args = @_;

    my $_dateBegin = $args{date_begin};    # YYYY-MM-DD or YYYY-DD-MM
    my $_dateEnd   = $args{date_end};      # YYYY-MM-DD or YYYY-DD-MM

    my $dateBegin = $_dateBegin;

    my ( $beginYear, $beginMonth, $beginDay ) = split( "-", $_dateBegin );
    my ( $endYear,   $endMonth,   $endDay )   = split( "-", $_dateEnd );

    if ( $endMonth > 12 ) {
        $dateBegin = join( "-", $beginYear, $beginDay, $beginMonth );    # swap the month/day fields
    }

    return $self->SUPER::_getDates( date_begin => $dateBegin );
}

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