package RPS::Import::RSFormatFull;

use strict;

use Data::Dumper;

use Date::Calc qw(Days_in_Month Add_Delta_Days);

use lib '/app/tools/common/lib';
use Common::Util;
use Common::Consts;
use Common::RSMath qw(round);
use Common::Locale;

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

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

my %channelMap = (
    retail       => RPS::File::Sale::CHANNEL_RETAIL,
    military     => RPS::File::Sale::CHANNEL_MILITARY,
    px           => RPS::File::Sale::CHANNEL_MILITARY,
    club         => RPS::File::Sale::CHANNEL_CLUB,
    'mail order' => RPS::File::Sale::CHANNEL_MAILORDER,
    direct       => RPS::File::Sale::CHANNEL_DIRECT,
);

# map version num to the field order
my %fieldMap = (
    2 => {
        'outlet'       => 0,
        'country'      => 1,
        'date'         => 2,
        'artist'       => 3,
        'catno'        => 4,
        'album'        => 5,
        'upc'          => 6,
        'sales'        => 7,
        'salesprice'   => 8,
        'returns'      => 9,
        'returnsprice' => 10,
        'net'          => 11,
        'netprice'     => 12,
        'currency'     => 13,
        'netusd'       => 14,
        'format'       => 16,
    },
    3 => {
        'outlet'       => 0,
        'country'      => 1,
        'date'         => 2,
        'artist'       => 3,
        'catno'        => 4,
        'album'        => 5,
        'format'       => 6,
        'upc'          => 7,
        'channel'      => 8,
        'pricelevel'   => 9,
        'sales'        => 10,
        'salesprice'   => 11,
        'returns'      => 12,
        'returnsprice' => 13,
        'net'          => 14,
        'netprice'     => 15,
        'currency'     => 16,
        'netusd'       => 17,
    },

    # !!! Deprecated - mcps
    4 => {
        'outlet'         => 0,
        'country'        => 1,
        'date'           => 2,
        'artist'         => 3,
        'catno'          => 4,
        'album'          => 5,
        'format'         => 6,
        'upc'            => 7,
        'channel'        => 8,
        'pricelevel'     => 9,
        'currency'       => 10,
        'wholesaleprice' => 11,
        'price'          => 12,
        'sales'          => 13,
        'salesprice'     => 14,
        'returns'        => 15,
        'returnsprice'   => 16,
        'net'            => 17,
        'netprice'       => 18,
        'free'           => 19,
        'adjustment'     => 20,
        'royaltytype'    => 21,
        'comments'       => 22,
    },
);

#public methods

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

    my $lines   = $args{lines};
    my $fileObj = $args{file};
    my $version = $self->_version;

    return undef unless ( defined $lines && defined $version );

    if ( $version == 4 ) {
        $self->errstr("Invalid version of importer ($version)");
        return undef;
    }

    my $offsets;

    if ( exists $fieldMap{$version} ) {
        $offsets = $fieldMap{$version};
    } else {
        $self->errstr('wrong version');
        return 0;
    }

    my $linenum = 2;
    shift @$lines;    ## skip header

    $fileObj->Physical(1);

    foreach my $line (@$lines) {
        unless ( $line->[ $offsets->{country} ] ) {
            $linenum++;
            next;
        }

        my $price_level = RPS::File::Sale::PLEVEL_UNKNOWN;
        my $channel     = RPS::File::Sale::CHANNEL_RETAIL;
        if ( $version == 3 || $version == 4 ) {
            if ( $line->[ $offsets->{channel} ] ) {
                my $c = lc $line->[ $offsets->{channel} ];
                $channel = $channelMap{$c};
                unless ( defined $channel ) {
                    $self->errstr("unknown channel: $c");
                    return undef;
                }
            }
            if ( $line->[ $offsets->{pricelevel} ] ) {
                my $p = lc $line->[ $offsets->{pricelevel} ];
                $p = "unknown" if ( $p =~ /(\d)/ );
                if ( $p eq 'unknown' ) {
                    $price_level = RPS::File::Sale::PLEVEL_UNKNOWN;
                } elsif ( $p eq 'full' ) {
                    $price_level = RPS::File::Sale::PLEVEL_FULL;
                } elsif ( $p =~ m/^mid(line)?$/ ) {
                    $price_level = RPS::File::Sale::PLEVEL_MID;
                } elsif ( $p eq 'budget' ) {
                    $price_level = RPS::File::Sale::PLEVEL_BUDGET;
                } elsif ( $p eq 'promo' ) {
                    $price_level = RPS::File::Sale::PLEVEL_PROMO;
                } else {
                    $self->errstr("unknown price level: $p");
                }
            }
        }

        my ( $config, $prodtype );

        if ( $line->[ $offsets->{format} ] =~ m/^dvd$/i ) {
            $config   = "DVD";
            $prodtype = RPS::File::Sale::TYPE_DVD;
        } elsif ( $line->[ $offsets->{format} ] =~ m/^cd$/i ) {
            $config   = "CD";
            $prodtype = RPS::File::Sale::TYPE_CD;
        } elsif ( $line->[ $offsets->{format} ] =~ m/^lp$/i ) {
            $config   = "LP";
            $prodtype = RPS::File::Sale::TYPE_LP;
        } elsif ( $line->[ $offsets->{format} ] =~ m/^ep$/i ) {
            $config   = "EP";
            $prodtype = RPS::File::Sale::TYPE_EP;
        } elsif ( $line->[ $offsets->{format} ] =~ m/^cd2$/i ) {
            $config   = "CD2";
            $prodtype = RPS::File::Sale::TYPE_DBL_CD;
        } elsif ( $line->[ $offsets->{format} ] =~ m/^2cd$/i ) {
            $config   = "CD2";
            $prodtype = RPS::File::Sale::TYPE_DBL_CD;
        } elsif ( $line->[ $offsets->{format} ] =~ m/^vhs$/i ) {
            $config   = "VHS";
            $prodtype = RPS::File::Sale::TYPE_VHS;
        } elsif ( $line->[ $offsets->{format} ] =~ /DVDCD/i ) {
            $config   = "DVD/CD";
            $prodtype = RPS::File::Sale::TYPE_DVD_CD_SET;
        } elsif ( $line->[ $offsets->{format} ] =~ /cas/i ) {
            $config   = "CASS";
            $prodtype = RPS::File::Sale::TYPE_CASS;
        } elsif ( $line->[ $offsets->{format} ] =~ /CD5/i ) {
            $config   = "CD5";
            $prodtype = RPS::File::Sale::TYPE_CD_SIN;
        } else {
            $self->errstr( "unknown format: " . $line->[ $offsets->{format} ] );
            return undef;
        }

        my $catno  = $line->[ $offsets->{catno} ];
        my $outlet = $line->[ $offsets->{outlet} ];
        my $artist = $line->[ $offsets->{artist} ];
        my $album  = $line->[ $offsets->{album} ];
        my $upc    = Common::Util::normalize_upc( $line->[ $offsets->{upc} ] );

        my $countryCode;
        if ( $line->[ $offsets->{country} ] =~ m/^\w\w$/ ) {
            $countryCode = uc $line->[ $offsets->{country} ];
            $countryCode = 'GB' if ( $countryCode eq 'UK' );
        } else {
            $countryCode = $Common::Consts::COUNTRY_CODE{ lc $line->[ $offsets->{country} ] };
        }
        my $currencyCode = $line->[ $offsets->{currency} ];

        unless ($countryCode) {
            $self->errstr( "unknown country: " . $line->[ $offsets->{country} ] );
            return undef;
        }

        #	    my ($dateBegin, $dateEnd) = $self->_getDates($line->[$offsets->{date}]);
        my ( $dateBegin, $dateEnd ) =
          $self->_getDates( date_begin => $line->[ $offsets->{date} ], date_end => $line->[ $offsets->{date} ] );

        unless ( defined $dateBegin && defined $dateEnd ) {
            $self->errstr( "Line $linenum: couldn't get dates from '" . $line->[ $offsets->{date} ] . "'" );
            return undef;
        }

        my $sales   = round( $line->[ $offsets->{sales} ] );
        my $returns = round( $line->[ $offsets->{returns} ] );
        $returns *= -1 if ( $returns < 0 && $self->{clientID} != 27 );

        #$returns            *= -1;

        # JPK
        # Localization.
        # net_usd is really 'net_base_currency'.
        # Won't we need to be prepared to localize this regex?
        #
        # No - In theory all of the numeric values will always be in 'us'
        # format : 12345.67
        #
        my $price         = $line->[ $offsets->{price} ];
        my $wholesale     = $line->[ $offsets->{wholesaleprice} ];
        my $sales_price   = $line->[ $offsets->{salesprice} ];
        my $returns_price = $line->[ $offsets->{returnsprice} ];
        my $net_price     = $line->[ $offsets->{netprice} ];
        my $net_usd       = $line->[ $offsets->{netusd} ];
        $sales   = 0 if ( $sales eq "" );
        $returns = 0 if ( $returns eq "" );
        $returns_price *= -1 if ( $returns_price < 0 && $self->{clientID} != 27 );
        $returns *= -1 if ( $self->{clientID} == 27 );

        if ( sprintf( "%.2f", ( $sales_price - $returns_price ) ) != sprintf( "%.2f", $net_price )
            || $sales - $returns != $line->[ $offsets->{net} ] ) {
            print STDERR "Mismatched Sale/Returns/SalesRevenue/ReturnsRevenue l:" . $linenum . "\n";
            $self->errstr( "Mismatched Sale/Returns/SalesRevenue/ReturnsRevenue l:" . $linenum );
            return undef;
        }

        # JPK - This will need to get a little fancier.
        #
        my $convRate = 1;
        $convRate = 0 if ( $currencyCode ne Common::Client::Current()->Locale()->currencyFormat()->currencyCode() );
        if ( $currencyCode ne Common::Client::Current()->Locale()->currencyFormat()->currencyCode() ) {
            if ( $net_price != 0 && $net_usd != 0 ) {
                $convRate = $net_usd / $net_price;
                $sales_price   *= $convRate;
                $returns_price *= $convRate;
                $net_price     *= $convRate;
                $currencyCode = Common::Client::Current()->Locale()->currencyFormat()->currencyCode();
                $convRate     = 1;
            }
        }

        my $skip_sale = 0;
        if ( $outlet =~ /datapak/i && $self->{clientID} == 27 ) {
            $skip_sale = $self->_filterDatapakSale( $catno, $upc );
            if ( $skip_sale > 2 ) {
                $catno     = $skip_sale;
                $skip_sale = 0;
            }
            $catno =~ s/\s.*$//;
        }

        # If the 'free goods' flag is set, I don't believe we need to concern ourselves with any pricing.
        #
        my $free = uc( $line->[ $offsets->{free} ] ) eq 'Y' ? 1 : 0;
        if ($free) {
            $net_price = $sales_price = $returns_price = 0;
        }

        my $adjustment = uc( $line->[ $offsets->{adjustment} ] ) eq 'Y' ? 1 : 0;
        my $comments;
        if ($adjustment) {

            # !!! Only sale units should be specified for an adjustment.
            #
            $comments = $line->[ $offsets->{comments} ];
        }

        # Parse the 'Royalty Type' column, if any.
        #

        my $usMechStatus = 0;
        my $ukMechStatus = 0;
        my $labelStatus  = 0;
        my $artistStatus = 0;

        if ( defined $offsets->{royaltytype} ) {

            # !!! and canadian, someday...
            #
            my $royaltyType = $line->[ $offsets->{royaltytype} ];
            if ( $royaltyType && 'ALL' ne uc($royaltyType) ) {

                # Turn -off- all the types, and only enable those that were specified.
                #
                $usMechStatus = 2;
                $ukMechStatus = 2;
                $labelStatus  = 2;
                $artistStatus = 2;

                my @types = split( ',', $royaltyType );
                foreach my $type (@types) {
                    my $testType = uc($type);
                    $artistStatus = 0 if ( 'ARTIST' eq $testType );
                    $labelStatus  = 0 if ( 'LABEL' eq $testType );
                    $usMechStatus = 0 if ( 'US-MECH' eq $testType );
                    $ukMechStatus = 0 if ( 'UK-MECH' eq $testType );
                    $ukMechStatus = 0 if ( 'GB-MECH' eq $testType );    # Just in case...
                }
            }
        }

        if (   $prodtype
            && ( $free || $net_price != 0 || $sales_price != 0 || $returns_price != 0 || $sales != 0 || $returns != 0 )
            && ( $album || $upc || $catno )
            && $skip_sale == 0 ) {
            my $sale = RPS::Import::SaleRec->new();

            $sale->productType($prodtype);
            $sale->dateBegin($dateBegin);
            $sale->dateEnd($dateEnd);
            $sale->outlet($outlet);
            $sale->clientProductID($catno);
            $sale->artistName($artist);
            $sale->albumName($album);
            $sale->upc($upc);
            $sale->free($free);
            $sale->price($price);
            $sale->wholesalePrice($wholesale);
            $sale->sales($sales);
            $sale->salesRevenue($sales_price);
            $sale->returns($returns);
            $sale->returnsRevenue($returns_price);
            $sale->totalRevenue($net_price);
            $sale->priceLevel($price_level);
            $sale->channel($channel);
            $sale->configuration($config);
            $sale->countryCode($countryCode);
            $sale->currencyCode($currencyCode);
            $sale->conversionRate($convRate);
            $sale->lineNum($linenum);
            $sale->mcps_adjustment($adjustment);
            $sale->comments($comments);
            $sale->mechanical_royalty_status($usMechStatus);
            $sale->uk_mechanical_royalty_status($ukMechStatus);
            $sale->artist_royalty_status($artistStatus);
            $sale->label_royalty_status($labelStatus);

            $self->_insertSale( sale => $sale );
        } elsif ( $prodtype && $net_price ne "" && ( $album || $upc || $catno ) && $skip_sale == 1 ) {
            my @datapak_collection_catalog = ( 1088, 1099, 1152, 1170, 1236, 9034 );

            $sales_price   /= @datapak_collection_catalog;
            $returns_price /= @datapak_collection_catalog;
            $net_price     /= @datapak_collection_catalog;
            for ( my $x = 0 ; $x < @datapak_collection_catalog ; $x++ ) {
                print STDERR "Split 6 Remap 1228 -> " . $datapak_collection_catalog[$x] . "\n";
                my $sale = RPS::Import::SaleRec->new();

                $sale->productType($prodtype);
                $sale->dateBegin($dateBegin);
                $sale->dateEnd($dateEnd);
                $sale->outlet($outlet);
                $sale->clientProductID( $datapak_collection_catalog[$x] );
                $sale->artistName($artist);
                $sale->albumName($album);
                $sale->upc($upc);
                $sale->sales($sales);
                $sale->salesRevenue($sales_price);
                $sale->returns($returns);
                $sale->returnsRevenue($returns_price);
                $sale->totalRevenue($net_price);
                $sale->priceLevel($price_level);
                $sale->channel($channel);
                $sale->configuration($config);
                $sale->countryCode($countryCode);
                $sale->currencyCode($currencyCode);
                $sale->conversionRate($convRate);
                $sale->lineNum($linenum);

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

        #else { print STDERR "Skip l:".$linenum." p:".$prodtype." np:".$net_price." a:".$album." s:".$sales." r:".$returns."\n"; }
        $linenum++;
    }

    $fileObj->Physical(1);
    $fileObj->Save();
    return $linenum;
}

#
# Private methods
#

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

    if ( $date =~ m/^(\d{4}-\d\d-\d\d)$/ ) {
        return ( $1, $1 );
    } elsif ( $date =~ m/^(\d+)\/(\d+)\/(\d{4})$/ ) {
        my $tmp = sprintf( "%04d-%02d-%02d", $3, $2, $1 );
        return ( $tmp, $tmp );
    } elsif ( $date =~ m/^(\d{4})(\d{2})$/ ) {
        return ( $1 . "-" . $2 . "-01", $1 . "-" . $2 . "-" . Days_in_Month( $1, $2 ) );
    } elsif ( $date =~ m/^(\d+)$/ ) {
        ## stupid excel dates...
        my ( $year, $month, $day ) = Add_Delta_Days( 1900, 1, 1, $1 - 2 );
        my $tmp = sprintf( "%d-%02d-%02d", $year, $month, $day );
        return ( $tmp, $tmp );
    }
    return undef;
}

sub _filterDatapakSale {
    my $self         = shift;
    my $catalog      = shift;
    my $upc          = shift;
    my @datapak_skip = (
        1151, 1152, 1215, 1161, 1173, 1174, 1209, 1210, 1183, 1184, 1232, 1233, 1238, 1240, 1247, 1248,
        1235, 1267, 1269, 1272, 1274, 1278, 1280, 1281, 1283, 1300, 1302, 1328, 9149, 1316, 1317, 1319,
        1320, 1307, 1308, 1245, 1246, 1275, 1277, 1295, 1296, 1298, 1299, 1303, 1305, 1031, 1035
    );

    my %datapak_map = (
        1026 => 1031,
        1150 => 1152,
        1154 => 1215,
        1172 => 1174,
        1208 => 1210,
        1212 => 1212,
        1231 => 1233,
        1239 => 1240,
        1249 => 1247,
        1234 => 1267,
        1268 => 1269,
        1273 => 1274,
        1279 => 1280,
        1282 => 1283,
        1301 => 1302,
        1327 => 1328,
        1315 => 1317,
        1318 => 1320,
        1306 => 1308,
        1244 => 1246,
        1276 => 1277,
        1294 => 1296,
        1297 => 1299,
        1304 => 1305,
    );
    $catalog =~ s/\s.*$//;
    $upc =~ s/\s.*//;
    for ( my $x = 0 ; $x < @datapak_skip ; $x++ ) {
        return 2 if ( $catalog == $datapak_skip[$x] );
    }
    if ( defined $datapak_map{$catalog} ) {
        print STDERR "FOUND REMAP c:" . $catalog . " t:" . $datapak_map{$catalog} . "\n";
        return $datapak_map{$catalog};
    } elsif ( $catalog == 1228 ) {
        return 1;
    } else {
        return 0;
    }

}

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