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.
###
