package RPS::Import::Red;

use strict;

use Date::Calc qw(Days_in_Month Decode_Month);

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

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

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

my %fieldMap = (
    1 => {
        label    => 0,
        artist   => 1,
        album    => 2,
        sales    => 3,
        psales   => 4,
        returns  => 5,
        preturns => 6,
        total    => 8,
    },
    2 => {
        label    => 0,
        artist   => 2,
        album    => 3,
        cpid     => 5,
        catalog  => 6,
        sales    => 7,
        psales   => 8,
        returns  => 9,
        preturns => 10,
        total    => 12,
    },
    3 => {
        label    => 0,
        artist   => 1,
        album    => 2,
        cpid     => 4,
        catalog  => 5,
        sales    => 6,
        psales   => 7,
        returns  => 8,
        preturns => 9,
        total    => 11,
    },
    4 => {
        label    => 0,
        artist   => 1,
        album    => 2,
        cpid     => 4,
        catalog  => 5,
        sales    => 6,
        psales   => 7,
        returns  => 8,
        preturns => 9,
        total    => 11,
    },
    5 => {
        date_begin => 0,    # above header

        label  => 0,        # detail
        artist => 1,
        album  => 2,

        #cpid        => 4,
        catalog  => 3,
        sales    => 4,
        psales   => 5,
        returns  => 6,
        preturns => 7,
        total    => 9,
    },
    6 => {
        artist   => 2,
        album    => 3,
        cpid     => 5,
        catalog  => 6,
        upc      => 7,
        sales    => 8,
        psales   => 9,
        returns  => 10,
        preturns => 11,
        total    => 13,
    },
    7 => {
        artist   => 2,     # C
        album    => 3,     # D
        pfx      => 4,     # E
        catalog  => 7,     # H
        upc      => 6,     # G
        sales    => 8,     # I
        psales   => 9,     # J
        returns  => 10,    # K
        preturns => 11,    # L
        total    => 13,    # N
    },
    10 => {
        artist   => 2,     # C
        album    => 3,     # D
        pfx      => 4,     # E
        catalog  => 7,     # H
        upc      => 6,     # G
        sales    => 9,     # J
        psales   => 10,    # K
        returns  => 11,    # L
        preturns => 12,    # M
        total    => 14,    # O
    },
);

my %productTypeMap = (
    'lp'  => RPS::File::Sale::TYPE_LP,
    'dv'  => RPS::File::Sale::TYPE_DVD,
    'vd'  => RPS::File::Sale::TYPE_DVD,
    'cd'  => RPS::File::Sale::TYPE_CD,
    'el'  => RPS::File::Sale::TYPE_CD,
    'oth' => RPS::File::Sale::TYPE_LP5,       # See Case 13287
    'mv'  => RPS::File::Sale::TYPE_LP5,       # See Case 13287
    'xv'  => RPS::File::Sale::TYPE_LP,        # See Case 16197
    'x5'  => RPS::File::Sale::TYPE_CD_SIN,    # See Case 16197
    'tp'  => RPS::File::Sale::TYPE_CASS,      # See Case 15919
    'cs'  => RPS::File::Sale::TYPE_CASS,      # See Case 16029
);

#public methods

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

    if ( $version == 4 ) {
        return ( defined( $self->units ) && ( $self->trackName || $self->albumName ) );
    } else {
        return $self->SUPER::_isValidSaleRecord();
    }
}

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

    my $retval      = undef;
    my $lines       = $args{lines};
    my $fileObj     = $args{file};
    my $version     = $args{file}->VersionNum();
    my $fileName    = $fileObj->OrigFileName;
    my $sheet_names = $args{sheet_names};

    my ( $gDateBegin, $gDateEnd ) = $self->_getDates($fileName);
    my $offsets = $fieldMap{$version};

    my $linenum;
    my $sheet_count = 0;

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

        my $dateBegin;
        my $dateEnd;

        # FBoD 4664 - so, if it's version 7 and there is more than a single sheet, skip ones with "report" in the name.
        # the sample had a hidden tab named "Report (14)". awesome.
        if ( $version == 7 && scalar @{ $args{sheets} } > 1 && $sheet_names->[$sheet_count] =~ /report/i )    # summary sheet - skip
        {
            $sheet_count++;
            next;
        }

        foreach my $line (@$sheet) {
            my $prodtype = RPS::File::Sale::TYPE_PHYSICAL;

            my $price_level = $version =~ /^7|10$/ ? RPS::File::Sale::PLEVEL_UNKNOWN : RPS::File::Sale::PLEVEL_FULL;

            my $channel = RPS::File::Sale::CHANNEL_RETAIL;
            my $label   = $line->[ $offsets->{label} ];
            my $artist  = $line->[ $offsets->{artist} ];
            my $album   = $line->[ $offsets->{album} ];
            my $cpid    = $line->[ $offsets->{cpid} ] if ( defined $offsets->{cpid} );
            my $catalog = $line->[ $offsets->{catalog} ] if ( defined $offsets->{catalog} );
            my $pfx     = $line->[ $offsets->{pfx} ] if ( defined $offsets->{pfx} );
            my $upc;
            my $countryCode;

            if ( $version == 7 || $version == 10 ) {
                if ( $fileName =~ /CA(?:N)?/i )    # if file has CA or CAN
                {
                    $countryCode = "CA";
                } else {
                    print STDERR "Couldn't get territory from $fileName\n";
                    $self->errstr("Couldn't get territory from $fileName");
                    return undef;
                }
            } else {
                $countryCode = "US";
            }

            if ( !$dateBegin ) {
                if ( defined $offsets->{date_begin} ) {

                    # Grab date from first row of current sheet
                    #
                    my $_dateField = $line->[ $offsets->{date_begin} ];

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

                    unless ( $dateBegin && $dateEnd ) {
                        $self->errstr("couldn't get dates from $_dateField");
                        print STDERR "couldn't get dates from $_dateField\n";
                        return undef;
                    }
                } else {

                    # Use the date we pulled from the filename
                    #
                    if ( $gDateBegin && $gDateEnd ) {
                        $dateBegin = $gDateBegin;
                        $dateEnd   = $gDateEnd;
                    } else {
                        $self->errstr("couldn't get dates from filename $fileName");
                        print STDERR "couldn't get dates from filename $fileName\n";
                        return undef;
                    }
                }
            }

            if ( defined $offsets->{upc} ) {
                $upc = $line->[ $offsets->{upc} ];
            } elsif ( $catalog =~ /^\d+$/ ) {
                $upc     = $catalog;
                $catalog = '';
            }

            # Determine the product type
            #
            if ( $version == 5 ) {

                # The configuration may appear at the end of the catalog#
                # (if it doesn't, then assume it's a CD).
                #
                my $cfg = "cd";    # default
                if ( $catalog =~ m/(\D+)$/ ) {
                    $cfg      = $1;
                    $prodtype = $productTypeMap{ lc $cfg };
                }

                # The country code comes from the sheet name
                #
                if ( $sheet_names->[$sheet_count] =~ /ca/i ) {
                    $countryCode = 'CA';
                } elsif ( $sheet_names->[$sheet_count] !~ /us/i ) {
                    print STDERR "Unrecognized sheet name: " . $sheet_names->[$sheet_count] . "\n";
                    $self->errstr( "Can't determine country from " . $sheet_names->[$sheet_count] );
                    return undef;
                }
            } else {
                if ( $cpid && 'SEL-CFG' ne $cpid ) {
                    my ( $code, $cfg ) = split( "-", $cpid );
                    $prodtype = $productTypeMap{ lc $cfg };
                    if ( !$prodtype ) {
                        print STDERR "Can't determine product type from '$cpid' in line $linenum";
                        $self->errstr("Can't determine product type from '$cpid' in line $linenum");
                        return undef;
                    }
                }
                elsif ( $pfx && 'Pfx' ne $pfx ) {
                    if ( $pfx =~ /^(lp|16)$/i ) {
                        $prodtype = RPS::File::Sale::TYPE_LP;
                    }
                    elsif ( $pfx =~ /^26$/ ) {
                        $prodtype = RPS::File::Sale::TYPE_CASS;
                    }
                    elsif ( $pfx =~ /^(cd|el|31)$/i ) {
                        $prodtype = RPS::File::Sale::TYPE_CD;
                    }
                    elsif ( $pfx =~ /^si$/i ) {
                        $prodtype = RPS::File::Sale::TYPE_LP5;
                    }
                    elsif ( $pfx =~ /^vd|73$/i ) {
                        $prodtype = RPS::File::Sale::TYPE_DVD;
                    }
                    else {
                        print STDERR "Can't determine product type from pfx '$pfx' in line $linenum\n";
                        $self->errstr("Can't determine product type from '$pfx' in line $linenum");
                        return undef;
                    }
                }
            }

            if ( $album eq "Various" ) {
                $album  = $artist;
                $artist = "Various";
            }

            my ($sales)    = $line->[ $offsets->{sales} ] =~ m/^(-?\d+)$/;
            my ($psales)   = $line->[ $offsets->{psales} ] =~ m/^(-?\d*\.?\d*)$/;
            my ($returns)  = $line->[ $offsets->{returns} ] =~ m/^(-?\d+)$/;
            my ($preturns) = $line->[ $offsets->{preturns} ] =~ m/^(-?\d*\.?\d*)$/;
            my ($total)    = $line->[ $offsets->{total} ] =~ m/^(-?\d*\.?\d*)$/;

            if ( $sales <= 0 && $psales <= 0 ) {
                $returns  += $sales;
                $preturns += $psales;

                $sales  = 0;
                $psales = 0;
            }

            if ( $returns > 0 && $preturns > 0 ) {
                $sales  += $returns;
                $psales += $preturns;

                $returns  = 0;
                $preturns = 0;
            }

            if ( $sales > 0 && $psales < 0 ) {
                $preturns += $psales;
                $psales = 0;
            }

            $returns  = $returns * -1;
            $preturns = $preturns * -1;

            if ( $prodtype && ( $sales || $returns ) && $album ) {
                if ( !( $sales || $returns ) && $total ) {
                    $self->errstr("Line $linenum: $total revenue with no units");
                }

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

                $sale->productType($prodtype);
                $sale->dateBegin($dateBegin);
                $sale->dateEnd($dateEnd);
                # client_product_id is stored in 'Catalog' column of the v10 sales file
                if ($version == 10) {
                    $sale->clientProductID($catalog)     if ( defined $offsets->{catalog} );
                }
                else {
                    $sale->clientProductID($cpid)     if ( defined $offsets->{cpid} );
                }
                $sale->serviceProductID($catalog) if ( defined $offsets->{catalog} );
                $sale->upc($upc);
                $sale->labelName($label);
                $sale->artistName($artist);
                $sale->albumName($album);
                $sale->sales($sales);
                $sale->returns($returns);
                $sale->salesRevenue($psales);
                $sale->returnsRevenue($preturns);
                $sale->totalRevenue($total);
                $sale->priceLevel($price_level);
                $sale->channel($channel);
                $sale->countryCode($countryCode);
                $sale->currencyCode('USD');
                $sale->lineNum($linenum);

                ##$args{dumper}($sale);  ## for cmd-line testing
                $self->_insertSale( sale => $sale );
            }
            $linenum++;
        }
        $sheet_count++;
    }
    return $linenum;
}

#
# Private methods
#

sub _getDates {
    my $self = shift;
    my $date = shift;

    my ( $dateBegin, $dateEnd, $month, $year );
    if ( ($month, $year) = $date =~ m/(september|october|november|december|january|february|march|april|may|june|july|august)[\s_]*(\d{4})/i ) {
        $month     = Decode_Month($month);
        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        $dateEnd   = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
    } elsif ( $date =~ m/[\s_](\w{3,4}[\s_]\d{4})/i ) {
        my $d = new Common::Date($1);
        $dateBegin = $d->monthBegin;
        $dateEnd   = $d->monthEnd;
    } elsif ( $date =~ m/[\s_](\w{3,4})(\d{4})/i ) {
        my $d = new Common::Date( $1 . " " . $2 );
        $dateBegin = $d->monthBegin;
        $dateEnd   = $d->monthEnd;
    } elsif ( $date =~ m/^([a-z]+)(\d{4})/ ) {

        $month     = Decode_Month($1);
        $year      = $2;
        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        $dateEnd   = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );

    } else {
        return undef;
    }

    return ( $dateBegin, $dateEnd );
}

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