package RPS::Import::Echospin;

use strict;

use Date::Calc qw(Days_in_Month Add_Delta_Days Decode_Month);

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

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

# map version num to the field order
my %fieldMap = (
    1 => {
        'upc'     => 0,
        'artist'  => 1,
        'album'   => 2,
        'label'   => 3,
        'units'   => 7,
        'price'   => 10,
        'type'    => 11,
        'format'  => 12,
        'country' => 14,
        'period'  => 15,
    },
    2 => {
        'media'   => 0,
        'isrc'    => 1,
        'upc'     => 1,
        'artist'  => 3,
        'album'   => 5,
        'label'   => 4,
        'retail'  => 8,
        'units'   => 9,
        'price'   => 13,
        'type'    => 2,
        'format'  => 14,
        'country' => 15,
    },
);

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

#public methods

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

    my $lines    = $args{lines};
    my $fileObj  = $args{file};
    my $fileName = $fileObj->OrigFileName;
    my $version  = $fileObj->VersionNum;

    #my $fileName = $args{OrigFileName}; # for cmd-line testing
    #my $version = $args{version}; # for cmd-line testing

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

    my $offsets = $fieldMap{$version};

    my $prev_format;

    shift @$lines;    ## skip header
    my $linenum = 2;
    my ( $upc, $dateBegin, $dateEnd );
    ( $dateBegin, $dateEnd ) = $self->_getDates($fileName) if ( $version == 2 );
    foreach my $line (@$lines) {

        my ( $upc, $isrc );
        my $artist = $line->[ $offsets->{artist} ];
        $upc = Common::Util::normalize_upc( $line->[ $offsets->{upc} ] );
        $isrc = $line->[ $offsets->{isrc} ] if exists $offsets->{isrc};
        my $label   = $line->[ $offsets->{label} ];
        my $country = $line->[ $offsets->{country} ];

        next if ( $country =~ m/^$/ );

        if ( $country !~ m/^[A-Z][A-Z]$/ ) {
            $self->errstr("invalid country code: $country");
            return undef;
        }

        ( $dateBegin, $dateEnd ) = $self->_getDates( $line->[ $offsets->{period} ] ) if ( $version == 1 );
        unless ( defined $dateBegin && defined $dateEnd ) {
            $self->errstr( "couldn't get dates from " . $line->[ $offsets->{period} ] );
            return undef;
        }

        my $price_level = RPS::File::Sale::PLEVEL_FULL;
        my $channel     = RPS::File::Sale::CHANNEL_RETAIL;
        my ( $format, $prodtype, $album, $track );

        if ( $line->[ $offsets->{format} ] eq "Physical" ) {
            $prodtype = RPS::File::Sale::TYPE_CD;
            $album    = $line->[ $offsets->{album} ];
            if ( defined $prev_format && $prev_format ne "physical" ) {
                $self->errstr("mixed physical/digital file");
                return undef;
            }
            $prev_format = "physical";
        } elsif ( $line->[ $offsets->{format} ] eq "Digital" ) {
            $format = RPS::File::Sale::FORMAT_DOWNLOAD;
            if ( defined $prev_format && $prev_format ne "digital" ) {
                $self->errstr("mixed physical/digital file");
                return undef;
            }
            if ( ( $line->[ $offsets->{media} ] =~ /album/i && $version == 2 ) || ( $version == 1 ) ) {
                $prodtype = RPS::File::Sale::TYPE_ALBUM;
                $album    = $line->[ $offsets->{album} ];
            } else {
                $prodtype = RPS::File::Sale::TYPE_TRACK;
                $track    = $line->[ $offsets->{album} ];
            }
            $prev_format = "digital";
        } else {
            $self->errstr( "unknown format: " . $line->[ $offsets->{format} ] );
            return undef;
        }

        my ($units)        = $line->[ $offsets->{units} ];
        my ($price)        = $line->[ $offsets->{price} ];
        my ($retail_price) = $line->[ $offsets->{retail} ];
        if ( $prev_format eq "digital" && $price < 0 ) {
            $price *= -1;
            $price = ( $units != 0 ) ? ( $price / $units ) : 0;
            $price *= -1 if ( $price > 0 );

            #$units *= -1 if($units>0);
        } elsif ( $prev_format eq "digital" ) {
            $price = ( $units != 0 ) ? ( $price / $units ) : 0;
        }

        if ( ( $line->[ $offsets->{type} ] ne "Sale" ) && ( $line->[ $offsets->{type} ] ne "Return" ) ) {
            $self->errstr( "unknown transaction type: " . $line->[ $offsets->{type} ] );
            return undef;
        }

        if ( $prodtype && $units && $price && ( $album || $track ) && $country ) {
            my $sale = RPS::Import::SaleRec->new();

            $sale->productType($prodtype);
            $sale->dateBegin($dateBegin);
            $sale->dateEnd($dateEnd);
            $sale->upc($upc)   if ( $album ne "" );
            $sale->isrc($isrc) if ( $track ne "" );
            $sale->artistName($artist);
            $sale->albumName($album) if ( $album ne "" );
            $sale->trackName($track) if ( $track ne "" );
            $sale->labelName($label);

            if ( $prev_format eq 'digital' ) {
                $sale->formatType($format);
                $sale->units($units);
                $sale->price($price);
            } else {
                $sale->sales($units);
                $sale->salesRevenue($price);
                $sale->totalRevenue($price);
                $sale->priceLevel($price_level);
                $sale->channel($channel);
            }
            $sale->retailPrice($retail_price);
            $sale->countryCode($country);
            $sale->lineNum($linenum);

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

        #else { print STDERR "skip l:".$linenum." p:".$prodtype." u:".$units." pr:".$price." a:".$album." t:".$track." c:".$country."\n"; }
        $linenum++;
    }

    if ( $prev_format eq "physical" ) {
        $fileObj->Physical(1);
        $fileObj->Save();
    }
    return $linenum;
}

#
# Private methods
#

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

    my $beginDate;
    my $endDate;

    if ( $date =~ m/^(\d+)\/(\d+)\/(\d{4}) *- *(\d+)\/(\d+)\/(\d{4})$/ ) {
        my $dateBegin = sprintf( "%04d-%02d-%02d", $3, $1, $2 );
        my $dateEnd   = sprintf( "%04d-%02d-%02d", $6, $4, $5 );
        return ( $dateBegin, $dateEnd );
    } elsif ( $date =~ /Sales Report - Digital/ ) {
        $date =~ s/^.* - //g;
        $date =~ s/_.*$//;
        my ( $month, $year, $monthName, $dateBegin, $dateEnd );
        if ( $date =~ /(\d+)-(\d{4})/ ) {
            ( $month, $year ) = split( "-", $date );
            $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
            $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
        } else {
            ( $monthName, $year ) = split( " ", $date );
            $dateBegin = sprintf( "%04d-%02d-%02d", $year, Decode_Month($monthName), 1 );
            $dateEnd = sprintf( "%04d-%02d-%02d", $year, Decode_Month($monthName), Days_in_Month( $year, Decode_Month($monthName) ) );
        }
        return ( $dateBegin, $dateEnd );
    } elsif ( $date =~ /Sales Report - Physical/ ) {
        $date =~ s/^.* - //g;
        $date =~ s/\s.*$//;
        my ( $month, $year ) = split( "-", $date );
        my $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        my $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
        return ( $dateBegin, $dateEnd );
    }
    return undef;
}

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