package RPS::Import::Puretracks::v1;

use strict;

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

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

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 %field_map = (
    1 => {
        date_row        => 0,
        date_col        => 0,
        units           => 0,
        code            => 1,
        artist          => 2,
        title           => 3,
        price           => 2,
        deduct          => 2,
        deduct_alt      => 1,
        summary_product => 0,
    },
    2 => {
        date_row        => 0,
        date_col        => 0,
        units           => 1,
        code            => 2,
        artist          => 3,
        title           => 4,
        price           => 3,
        deduct          => 3,
        summary_product => 1,
    },
    3 => {
        date_col        => 1,
        date_start_row  => 8,
        date_end_row    => 9,
        units           => 0,
        code            => 1,
        artist          => 2,
        artist_track    => 3,
        title           => 3,
        title_track     => 4,
        price           => 2,
        deduct          => 2,
        summary_product => 0,
    },
    4 => {
        date_col        => 1,
        date_start_row  => 8,
        date_end_row    => 9,
        units           => 0,
        code            => 1,
        artist          => 2,
        artist_track    => 3,
        title           => 3,
        title_track     => 4,
        price           => 2,
        deduct          => 2,
        summary_product => 0,
    },
    5 => {
        date_col        => 0,
        units           => 1,
        code_track      => 2,
        artist          => 3,
        title           => 2,
        title_track     => 4,
        price           => 3,
        deduct          => 2,
        summary_product => 1,
    },
    6 => {
        date_col        => 0,
        units           => 1,
        code            => 2,
        code_track      => 2,
        artist          => 3,
        title           => 4,
        price           => 3,
        deduct          => 0,    # no-deductions??
        summary_product => 1,
    },
    7 => {
        date_col        => 1,
        date_start_row  => 8,
        date_end_row    => 9,
        units           => 9,
        code            => 4,
        artist          => 7,
        artist_track    => 7,
        title           => 8,
        title_track     => 8,
        price           => 3,
        detail_price    => 11,
        deduct          => 5,
        upc             => 2,
        isrc            => 3,
        spid            => 4,
        label           => 5,
        summary_product => 0,
    },
    8 => {
        date_col        => 0,
        units           => 1,
        code            => 2,
        code_track      => 2,
        artist          => 3,
        title           => 4,
        price           => 2,
        deduct          => 4,    # no-deductions??
        summary_product => 0,
    },
    10 => {
        date_col        => 1,
        date_start_row  => 9,
        date_end_row    => 10,
        units           => 0,
        code            => 1,
        artist          => 2,
        artist_track    => 3,
        title           => 3,
        title_track     => 4,
        price           => 2,
        deduct          => 4,
        summary_product => 0,
    },
    9 => {
        date_col        => 1,
        date_start_row  => 8,
        date_end_row    => 9,
        units           => 0,
        code            => 1,
        artist          => 2,
        artist_track    => 3,
        title           => 3,
        title_track     => 4,
        price           => 3,
        deduct          => 5,
        summary_product => 0,
        upc             => 1,
        isrc            => 1,

        #spid            => 4,
        #label           => 5,
    },
    11 => {
        date_col        => 1,
        date_start_row  => 9,
        date_end_row    => 10,
        units           => 1,
        code            => 2,
        artist          => 4,
        title           => 5,
        price           => 3,
        deduct          => 5,
        summary_product => 0,
    },
);

#public methods

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

    my $sheets   = $args{sheets};
    my $version  = $self->_version();
    my $fileName = $args{file}->OrigFileName;

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

    my $offsets = $field_map{$version};

    my $summary = $sheets->[0];
    my $albums  = $sheets->[1];
    my $tracks  = $sheets->[2];

    my ( $country, $currency );
    if ( $fileName =~ m/ US / || $fileName =~ /_US_/ || $fileName =~ /^US_/ ) {
        $country  = 'US';
        $currency = 'USD';
    } else {
        $country  = 'CA';
        $currency = 'CAD';
    }

    my ( $album_price, $track_price, $month );
    my ( $albumDeduct, $trackDeduct );
    my $in_pub_deduct = 0;
    my ( $priceColumn, $deductionColumn );
    foreach my $line (@$summary) {
        if ( $version == 11 ) {
            if ( $line->[0] eq "Type" ) {
                my @columns = @$line;
                for ( my $x = 0 ; $x < @columns ; $x++ ) {
                    $priceColumn     = $x if ( $line->[$x] =~ /net payment/i );
                    $deductionColumn = $x if ( $line->[$x] =~ /deduction/i );
                }
            } elsif ( $line->[ $offsets->{summary_product} ] eq "Product" && $album_price eq "" ) {
                $album_price = $line->[$priceColumn];
                $album_price /= $line->[1] if ( $line->[1] != 0 );
                $albumDeduct = 0;
            } elsif ( $line->[ $offsets->{summary_product} ] eq "Track" && $track_price eq "" ) {
                $track_price = $line->[$priceColumn];
                $track_price /= $line->[1] if ( $line->[1] != 0 );
                $trackDeduct = 0;
            }
        } elsif ( (
                   $line->[ $offsets->{summary_product} ] eq "Product"
                || $line->[ $offsets->{summary_product} ] eq "Albums"
                || $line->[ $offsets->{summary_product} ] eq "Album"
            )
            && ( $version > 6 )
          ) {
            $album_price = $line->[ $offsets->{price} ];
            $albumDeduct = $line->[ $offsets->{deduct} ] / $line->[1] if ( $line->[1] > 0 );

        } elsif ( ( $line->[ $offsets->{summary_product} ] eq "Track" && $version > 6 )
            || ( $line->[ $offsets->{summary_product} ] eq "Tracks" && $version > 6 ) ) {
            $track_price = $line->[ $offsets->{price} ];
            $trackDeduct = $line->[ $offsets->{deduct} ] / $line->[1] if ( $line->[1] > 0 );

        } elsif ( $line->[ $offsets->{summary_product} ] =~ /^(Albums|Product)$/ ) {
            if ( $version =~ /^(5|6)$/ ) {
                $month = Decode_Month( $line->[ $offsets->{month} ] );
                $album_price->{$month} = $line->[ $offsets->{price} ];
            } else {
                $album_price = $line->[ $offsets->{price} ];
            }
        } elsif ( $line->[ $offsets->{summary_product} ] =~ /^Track/ ) {
            if ( $version =~ /^(5|6)$/ ) {
                $track_price->{$month} = $line->[ $offsets->{price} ];
            } else {
                $track_price = $line->[ $offsets->{price} ];
            }
        } elsif ( $line->[0] =~ /Publishing Deduction?/
            || $line->[1] =~ /Publishing Deduction/i
            || ( $in_pub_deduct && $version !~ /^(3|4)$/ ) ) {
            $in_pub_deduct = 1;

            $albumDeduct ||=
                $line->[ $offsets->{deduct} ] =~ m/^\$(\d+\.\d\d)\/per Albums?$/     ? $1
              : $line->[ $offsets->{deduct_alt} ] =~ m/^\$(\d+\.\d\d)\/per Albums?$/ ? $1
              : (    $line->[ $offsets->{summary_product} ] =~ m/album/i
                  && $line->[ $offsets->{deduct} ] =~ m/^(\d+(\.\d+)?)$/ ) ? $1
              : 0;

            $trackDeduct ||=
                $line->[ $offsets->{deduct} ] =~ m/^\$(\d+\.\d\d)\/per Tracks?$/     ? $1
              : $line->[ $offsets->{deduct_alt} ] =~ m/^\$(\d+\.\d\d)\/per Tracks?$/ ? $1
              : (    $line->[ $offsets->{summary_product} ] =~ m/track/i
                  && $line->[ $offsets->{deduct} ] =~ m/^(\d+(\.\d+)?)$/ ) ? $1
              : 0;
        }
    }

    if ( $album_price eq "" && $track_price eq "" ) {
        $self->errstr("couldn't get prices");
        return undef;
    }

    if ( $version =~ /^(5|6)$/ ) {
        map { $album_price->{$_} -= $albumDeduct } keys %$album_price;
        map { $track_price->{$_} -= $trackDeduct } keys %$track_price;
    } else {
        $album_price -= $albumDeduct;

        $track_price -= $trackDeduct;

    }

    my ( $dateBegin, $dateEnd );
    if ( $version == 8 ) {
        my $adjusted_filename = $fileName;
        $adjusted_filename =~ s/^.*US /Summary / if ( $fileName =~ /US/ );
        $adjusted_filename =~ s/^.*CA /Summary / if ( $fileName =~ /CA/ );
        $adjusted_filename =~ s/\.xls//;
        ( $dateBegin, $dateEnd ) = $self->_getDates($adjusted_filename);
    } elsif ( $version == 1 || $version == 2 ) {
        ( $dateBegin, $dateEnd ) = $self->_getDates( $summary->[ $offsets->{date_row} ]->[ $offsets->{date_col} ] );
        unless ( $dateBegin && $dateEnd ) {
            $self->errstr("couldn't get dates");
            print STDERR 'dates: ' . $summary->[ $offsets->{date_row} ]->[ $offsets->{date_col} ] . "\n";
            return undef;
        }
    } elsif ( $version > 7 ) {
        my @name_parts;
        $fileName =~ m/(\d{8})\-(\d{8})/;
        if ( $fileName =~ m/(\d{8})\-(\d{8})/ ) {
            $name_parts[0] = $1;
            $name_parts[1] = $2;
        } elsif ( $fileName =~ m/(\d{8}) \- (\d{8})/ ) {
            $name_parts[0] = $1;
            $name_parts[1] = $2;
        } elsif ( $fileName =~ m/(\d{8})\_\-\_(\d{8})/ ) {
            $name_parts[0] = $1;
            $name_parts[1] = $2;
        }
        ( $dateBegin, $dateEnd ) = $self->_getDates_alt( $name_parts[0], $name_parts[1] );
        unless ( $dateBegin && $dateEnd ) {
            $self->errstr("couldn't get dates");
            print STDERR 'dates: ' . $name_parts[0] . ", " . $name_parts[1] . "\n";
            return undef;
        }
    } elsif ( $version !~ /(5|6)/ ) {
        ( $dateBegin, $dateEnd ) = $self->_getDates_alt(
            $summary->[ $offsets->{date_start_row} ]->[ $offsets->{date_col} ],
            $summary->[ $offsets->{date_end_row} ]->[ $offsets->{date_col} ]
        );
        unless ( $dateBegin && $dateEnd ) {
            $self->errstr("couldn't get dates");
            print STDERR 'dates: ' . $summary->[ $offsets->{date_start_row} ]->[ $offsets->{date_col} ] . "\n";
            return undef;
        }
    }
    my $linenum =
      $self->_processLines( $albums, RPS::File::Sale::TYPE_ALBUM, $dateBegin, $dateEnd, $album_price, $country, $currency, $offsets,
        $version, $fileName );

    # on the track tab some of the columns shift (for some versions)
    foreach my $k (qw(artist title code)) {
        my $trackKey = $k . '_track';
        $offsets->{$k} = $offsets->{$trackKey} if ( exists $offsets->{$trackKey} );
    }

    $linenum +=
      $self->_processLines( $tracks, RPS::File::Sale::TYPE_TRACK, $dateBegin, $dateEnd, $track_price, $country, $currency, $offsets,
        $version, $fileName );

    return $linenum;
}

#
# Private methods
#

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

    my ( $dateBegin, $dateEnd );
    if ( $date =~ m/Q(\d) (\d{4})/ ) {
        my $year = $2;
        my $qtr  = $1;
        if ( $qtr == 1 ) {
            $dateBegin = $year . "-01-01";
            $dateEnd = $year . "-03-" . Days_in_Month( $year, 3 );
        } elsif ( $qtr == 2 ) {
            $dateBegin = $year . "-04-01";
            $dateEnd = $year . "-06-" . Days_in_Month( $year, 6 );
        } elsif ( $qtr == 3 ) {
            $dateBegin = $year . "-07-01";
            $dateEnd = $year . "-09-" . Days_in_Month( $year, 9 );
        } elsif ( $qtr == 4 ) {
            $dateBegin = $year . "-10-01";
            $dateEnd = $year . "-12-" . Days_in_Month( $year, 12 );
        }
    } elsif ( $date =~ m/Summary\s*(\w+)\s+(\d{4})$/ ) {
        my $month = Decode_Month($1);
        my $year  = $2;
        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
    }

    return ( $dateBegin, $dateEnd );
}

sub _getDates_alt {
    my $self  = shift;
    my $date1 = shift;
    my $date2 = shift;
    my ( $dateBegin, $dateEnd );

    if ( $date1 =~ m/(\d{4})(\d\d)(\d\d)/ ) {
        $dateBegin = sprintf( "%04d-%02d-%02d", $1, $2, $3 );
    } elsif ( $date1 =~ m/^(\d+)$/ ) {
        my ( $year, $month, $day ) = Add_Delta_Days( 1900, 1, 1, $1 - 2 );
        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
    }
    if ( $date2 =~ m/(\d{4})(\d\d)(\d\d)/ ) {
        $dateEnd = sprintf( "%04d-%02d-%02d", $1, $2, $3 );
    } elsif ( $date2 =~ m/^(\d+)$/ ) {
        my ( $year, $month, $day ) = Add_Delta_Days( 1900, 1, 1, $1 - 2 );
        $dateEnd = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
    }

    return ( $dateBegin, $dateEnd );
}

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

    return undef unless ( $date =~ m/^(\w+)\D+\d+\D+(\d\d\d\d)$/ );
    my $year  = $2;
    my $month = Decode_Month($1);

    return undef unless ( $month && $year );
    return ( sprintf( "%04d-%02d-01", $year, $month ), sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) ), $month );
}

sub _processLines {
    my $self      = shift;
    my $lines     = shift;
    my $prodtype  = shift;
    my $dateBegin = shift;
    my $dateEnd   = shift;
    my $price     = shift;
    my $country   = shift;
    my $currency  = shift;
    my $offsets   = shift;
    my $version   = shift;
    my $fileName  = shift;
    my $dates     = $dateBegin ? 1 : 0;
    my $month     = 0;
    my $format    = RPS::File::Sale::FORMAT_DOWNLOAD;

    my $linenum = 1;    ## starting off after header

    if ( $version == 8 && $fileName =~ /US/ && $prodtype eq "A" ) {
        $offsets->{artist} -= 1;
        $offsets->{units}  -= 1;
        $offsets->{title}  -= 1;
    }
    if ( $version == 8 && $fileName =~ /US/ && $prodtype eq "T" ) {
        $offsets->{artist} += 1;
        $offsets->{units}  += 1;
        $offsets->{title}  += 1;
    }

    foreach my $line (@$lines) {
        my $artist     = $line->[ $offsets->{artist} ];
        my ($units)    = $line->[ $offsets->{units} ] =~ m/^(\d+)$/;
        my $title      = $line->[ $offsets->{title} ];
        my $test_title = $title =~ s/(\d)|\.//g;

        my $code = exists $offsets->{code} ? $line->[ $offsets->{code} ] : '';
        $code =~ s/^indy_//;
        $code =~ s/_mp3$//;

        unless ( $units && defined $price && ( $code || $artist || $title ) ) {
            $linenum++;
            next;
        }
        my ( $label, $upc, $isrc, $spid );
        $label = $line->[ $offsets->{label} ] if ( defined $offsets->{label} );
        $upc   = $line->[ $offsets->{upc} ]   if ( defined $offsets->{upc} );
        $upc =~ s/^indy_//;
        $upc =~ s/_mp3$//;
        $isrc = $line->[ $offsets->{isrc} ] if ( defined $offsets->{isrc} );
        $spid = $line->[ $offsets->{spid} ] if ( defined $offsets->{spid} );
        $isrc =~ s/\-//g;

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

        # if the date range wasn't passed, it will be grabbed from each data row
        # the month will be used to index the price array
        unless ($dates) {
            ( $dateBegin, $dateEnd, $month ) = $self->_getDataRowDate( $line->[ $offsets->{date_col} ] );
            unless ( $dateBegin && $month ) {
                $self->errstr("couldn't get dates");
                print STDERR 'date: ' . $line->[ $offsets->{date_col} ] . "\n";
                return undef;
            }
            $sale->price( $price->{$month} );
        } else {
            if ( $version == 7 ) {
                my $price     = $line->[ $offsets->{detail_price} ];
                my $deduction = $line->[ $offsets->{detail_price} + 1 ];
                $price -= $deduction;
                $price /= $units;
                $sale->price($price);
            } else {
                $sale->price($price);
            }
        }
        if ( $test_title eq "" && $version == 11 && $line->[ $offsets->{title} + 1 ] ne "" ) {
            my $new_test_title = $line->[ $offsets->{title} + 1 ];
            $new_test_title =~ s/(\d)|\.//g;
            if ( $new_test_title ne "" ) {
                $title = $line->[ $offsets->{title} + 1 ];
            }
        }
        $sale->productType($prodtype);
        $sale->formatType($format);
        $sale->dateBegin($dateBegin);
        $sale->dateEnd($dateEnd);
        $sale->artistName($artist);

        if ( $prodtype eq RPS::File::Sale::TYPE_ALBUM ) {
            $sale->upc($code);
            $sale->upc($upc) if ( defined $offsets->{upc} && $upc ne "" );
            $sale->albumName($title);
        } elsif ( $prodtype eq RPS::File::Sale::TYPE_TRACK ) {
            if ( $version != 9 ) {
                $sale->upc($upc) if ( defined $offsets->{upc} && $upc ne "" );
            }
            $sale->isrc($code);
            $sale->isrc($isrc) if ( defined $offsets->{isrc} && $isrc ne "" );
            $sale->trackName($title);
        }

        $sale->labelName($label)       if ( defined $offsets->{label} && $label ne "" );
        $sale->serviceProductID($spid) if ( defined $offsets->{spid}  && $spid ne "" );
        $sale->units($units);
        $sale->countryCode($country);
        $sale->currencyCode($currency);
        $sale->lineNum($linenum);

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

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