package RPS::Import::ADA::v12;

use strict;

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

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

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

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

# non-standard _fieldMap; need to override _importLines
sub _fieldMap {
    {
        'domestic' => {
            label       => 28,    # AC
            serviceName => 2,     # C
            dateBegin   => 3,     # D
            dateEnd     => 4,     # E
            productType => 17,    # R
            formatType  => 41,    # AP
            artistName  => 7,     # H
            upc         => 20,    # U
            albumName   => 22,    # W
            isrc        => 18,    # S
            trackName   => 9,     # J
            units       => 10,    # K
            price       => 15,    # P
            mediaType   => 17,    # R
            mediaCode   => 41,    # AP
            streamFlag  => 44,    # AS
        },
        'international' => {
            label       => 0,     # A
            serviceName => 5,     # F
            countryCode => 7,     # H

            productType => 9,     # J
            formatType  => 9,     # J
            mediaType   => 9,     # J

            artistName => 1,      # B

            albumName => 2,       # C
            trackName => 2,       # C

            isrc => 3,            # D
            upc  => 3,            # D

            units => 11,          # L
            price => 12,          # M
        },
    };
}

my %mediaCodeMap = (
    'DRMUPGR' => {
        format_type => RPS::File::Sale::FORMAT_DOWNLOADUPGRADE,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'DUALDIST' => {
        format_type => RPS::File::Sale::FORMAT_DUALDOWNLOAD,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'PERMDWNL' => {
        format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'PERMVDLD' => {
        format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'SUBAICLD' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'SUBASONE' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'SUBASPPE' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'SUBVICLD' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'SUBVSONE' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'SUBVSPPE' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'UGMV' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'UGRWRMST' => {
        format_type => RPS::File::Sale::FORMAT_RINGTONE,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'UGV' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeVideo,
    },
    'WRMST' => {
        format_type => RPS::File::Sale::FORMAT_RINGTONE,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'WRRNGBK' => {
        format_type => RPS::File::Sale::FORMAT_RINGTONE,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
    'WRSTREAM' => {
        format_type => RPS::File::Sale::FORMAT_STREAM,
        media_type  => RPS::DB::Item::MediaType::kMediaTypeAudio,
    },
);

# International delivery format mappings
#
my %deliveryFormatMap = (
    'EMASTERTONE' => {
        format_type  => RPS::File::Sale::FORMAT_RINGTONE,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        product_type => RPS::File::Sale::TYPE_TRACK,
    },
    'EMDALBUM' => {
        format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        product_type => RPS::File::Sale::TYPE_ALBUM,
    },
    'EMDALBUMSTREAMING' => {
        format_type  => RPS::File::Sale::FORMAT_STREAM,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        product_type => RPS::File::Sale::TYPE_ALBUM,
    },
    'EMDTRACK' => {
        format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        product_type => RPS::File::Sale::TYPE_TRACK,
    },
    'EMDTRACKSTREAMING' => {
        format_type  => RPS::File::Sale::FORMAT_STREAM,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        product_type => RPS::File::Sale::TYPE_TRACK,
    },
    'ERINGBACK' => {
        format_type  => RPS::File::Sale::FORMAT_RINGTONE,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        product_type => RPS::File::Sale::TYPE_TRACK,
    },
    'EVD' => {
        format_type  => RPS::File::Sale::FORMAT_DOWNLOAD,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
        product_type => RPS::File::Sale::TYPE_TRACK,
    },
    'EVDSTREAMING' => {
        format_type  => RPS::File::Sale::FORMAT_STREAM,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeVideo,
        product_type => RPS::File::Sale::TYPE_TRACK,
    },
);

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 $currencyCode = 'USD';

    foreach my $sheet ( @{ $args{sheets} } ) {

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

        my $sheetIndex = $self->_normalizeSheetName( lc $sheetName );

        if ( !exists $offsets->{$sheetIndex} ) {
            print STDERR "ADABase: Illegal sheet '$sheetName'\n";
            $self->errstr("Sheet '$sheetName' is not valid");
            return undef;
        }

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

        my ( $gDateBegin, $gDateEnd );
        if ( !defined $data->{dateBegin} ) {
            ( $gDateBegin, $gDateEnd ) = $self->_getDatesFromFileName($fileName);
        }

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

            my $sn       = $sheet_count + 1;             # sheet number (1-based)
            my $lineInfo = "Sheet $sn, line $linenum";

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

            # Skipping header
            #
            if (   !$serviceName
                || ( $serviceName && '' eq $serviceName )
                || ( $serviceName && ( 'vendor' eq lc($serviceName) ) )
                || ( $serviceName && ( 'provider' eq lc($serviceName) ) ) ) {
                $linenum++;
                next;
            }

            my $countryCode;
            if ( defined $data->{countryCode} ) {
                $countryCode = $line->[ $data->{countryCode} ];
            } else {
                $countryCode = 'US';
            }

            my $productType;
            my $formatType;
            my $mediaType;

            if ( defined $data->{mediaCode} ) {

                # Domestic Sales
                #
                my $mediaCode = $line->[ $data->{mediaCode} ];
                if ($mediaCode) {
                    $formatType = $mediaCodeMap{ uc $mediaCode }->{format_type};
                    $mediaType  = $mediaCodeMap{ uc $mediaCode }->{media_type};

                    if ( !$formatType && !$mediaType ) {
                        $self->errstr("$lineInfo: Unknown media code '$mediaCode'");
                        return undef;
                    }
                } else {
                    $self->errstr("$lineInfo: Media Code not found");
                    return undef;
                }

                my $_productType = uc $line->[ $data->{productType} ];

                if ( $_productType eq 'D' || $_productType eq 'P' || $_productType eq 'T' || $_productType eq 'S' ) {
                    $productType = RPS::File::Sale::TYPE_TRACK;
                } elsif ( $_productType eq 'A' ) {
                    $productType = RPS::File::Sale::TYPE_ALBUM;
                } else {
                    $self->errstr("$lineInfo: Unknown product type '$_productType'");
                    return undef;
                }

            } else {

                # International Sales
                #
                my $deliveryFormat = $line->[ $data->{productType} ];

                $formatType  = $deliveryFormatMap{ uc $deliveryFormat }->{format_type};
                $mediaType   = $deliveryFormatMap{ uc $deliveryFormat }->{media_type};
                $productType = $deliveryFormatMap{ uc $deliveryFormat }->{product_type};

                if ( !$productType ) {
                    $self->errstr("$lineInfo: Unknown product type '$deliveryFormat'");
                    return undef;
                }

            }

            my $trackName;
            my $albumName;
            my $isrc;
            my $upc;

            if ( $productType eq RPS::File::Sale::TYPE_TRACK ) {
                $isrc = $line->[ $data->{isrc} ] if ( defined $data->{isrc} );
                $trackName = $line->[ $data->{trackName} ];

                # On the domestic sheet, album name is always included.
                #
                if ( $sheetIndex eq 'domestic' ) {
                    $albumName = $line->[ $data->{albumName} ];
                }
            } elsif ( $productType eq RPS::File::Sale::TYPE_ALBUM ) {
                $albumName = $line->[ $data->{albumName} ];
                $upc = $line->[ $data->{upc} ] if ( defined $data->{upc} );
            }

            my $artistName = $line->[ $data->{artistName} ];
            my $units      = $line->[ $data->{units} ];
            my $price      = $line->[ $data->{price} ];
            my $label      = $line->[ $data->{label} ];

            my ( $dateBegin, $dateEnd );
            if ( defined $data->{dateBegin} ) {
                my $saleDateBegin = _normalizeDate( $line->[ $data->{dateBegin} ] );
                ( $dateBegin, $dateEnd ) = $self->_getDates( date_begin => $saleDateBegin );
            } else {
                ( $dateBegin, $dateEnd ) = ( $gDateBegin, $gDateEnd );
            }

            if ( $units && $units < 0 && $price && $price > 0 ) {
                $self->errstr("$lineInfo: Negative units with revenue");
                return undef;
            }

            if ( !$units && $price && $price < 0 ) {

                # We're just going to skip this line if it has negative revenue and no units.
                $linenum++;
                next;
            }

            if ( $units != 0 ) {
                $price /= ( $units * -1 ) if ( $units < 0 );
                $price /= $units if ( $units > 0 );
                if ( $price < 0 ) {
                    if ( $units > 0 ) {
                        $units *= -1;
                    }
                    $price *= -1;
                }
            }

            if ( defined $data->{serviceName} ) {
                $serviceID = $self->getServiceID( lc($serviceName) ) || $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $serviceName };

                if ( !$serviceID ) {

                    # Trying to get the Korean names to match up...
                    my $serviceNameCopy = $serviceName;
                    $serviceNameCopy =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg;
                    $serviceID = $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $serviceNameCopy };
                }
            }

            if ( $productType && $artistName && lc($artistName) ne "artist" && ( $albumName || $trackName ) ) {
                if ( defined $data->{serviceName} ) {
                    unless ($serviceID) {

                        if ( $serviceName =~ /[[:^ascii:]]/ ) {

                            # Case 15436 - defaulting service names with incompatible characters to ADA
                            $serviceID = Client::Service::DSP_ADA;
                        } else {
                            $self->errstr( "$lineInfo: Couldn't find service ID for: " . $serviceName );
                            return undef;
                        }
                    }
                }

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

                $sale->productType($productType);
                $sale->formatType($formatType);
                $sale->dateBegin($dateBegin);
                $sale->dateEnd($dateEnd);
                $sale->labelName($label) if ( defined $data->{label} && $label ne "" );
                $sale->albumName($albumName);
                $sale->trackName($trackName);
                $sale->isrc( Common::Util::normalize_isrc($isrc) ) if ($isrc);
                $sale->upc( Common::Util::normalize_upc($upc) )    if ($upc);
                $sale->serviceID($serviceID)                       if ($serviceName);
                $sale->artistName($artistName);
                $sale->units($units);
                $sale->price($price);
                $sale->countryCode($countryCode);
                $sale->currencyCode($currencyCode);
                $sale->mediaType($mediaType);
                $sale->lineNum($linenum);

                my $free = $price == 0 ? 1 : 0;
                $sale->free($free);

                $self->_insertSale( sale => $sale );
            } else {
                print STDERR "skip s: $sheetIndex l:"
                  . $linenum . " a:"
                  . $artistName . " t:"
                  . $albumName . " u:"
                  . $units . " p:"
                  . $price . "\n";
            }
            $linenum++;
        }
        $sheet_count++;
    }

    return $linenum;
}

sub _normalizeSheetName {
    my $self  = shift;
    my $sname = shift;
    my $name;

    $name = $sname;
    if ( $sname =~ /domestic digital/i ) {
        $name = "domestic";
    } elsif ( $sname =~ /int\'l digital/i ) {
        $name = "international";
    }

    return $name;
}

sub _normalizeDate {
    my ($dt) = @_;
    my $date = $dt;
    if ( $dt =~ m/^\d{5}$/ ) {
        $date = Spreadsheet::ParseExcel::Utility::ExcelFmt( "yyyy-mm-dd", $dt );
    }
    return $date;
}

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

    my ( $dateBegin, $dateEnd, $month, $year );

    if ( $date =~ m/(january|february|march|april|may|june|july|august|september|october|november|december)_(\d{4})\./i ) {
        $month = Decode_Month($1);
        $year  = $2;

        #print STDERR "DEBUG: _getDatesFromFileName: fmonth($1) month($month) year($year)\n";
        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
    } elsif ( $date =~ m/(\w*)\s*(\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.
###
