package RPS::Import::RSOutFmt;

use strict;
use Date::Calc qw(Days_in_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';

# map version num to the field order
my %fieldMap = (
    1 => {
        'label'        => 0,
        'service_id'   => 1,
        'service_name' => 2,
        'country'      => 3,
        'start_date'   => 4,
        'end_date'     => 5,
        'ptype'        => 6,
        'format'       => 7,
        'catno'        => 8,
        'upc'          => 9,
        'album'        => 11,
        'artist'       => 12,
        'isrc'         => 18,
        'tracknum'     => 21,
        'track'        => 22,
        'units'        => 27,

        #'price'	    	=> 28,
        'ext_price' => 29,
        'currency'  => 30,
        'convrate'  => 31,
        'free'      => 34,
        'price'     => 36,
    },
    2 => {
        'label'        => 0,
        'service_id'   => 1,
        'service_name' => 2,
        'outlet'       => 2,
        'country'      => 4,
        'start_date'   => 5,
        'end_date'     => 6,
        'ptype'        => 7,
        'format'       => 8,
        'catno'        => 9,
        'upc'          => 10,
        'album'        => 12,
        'album_artist' => 13,
        'isrc'         => 19,
        'tracknum'     => 22,
        'track'        => 23,
        'artist'       => 24,
        'units'        => 28,
        'price'        => 29,
        'ext_price'    => 30,
        'currency'     => 31,
        'convrate'     => 32,
        'unit_price'   => 33,
        'free'         => 35,
        'dist_fee'     => 36,
        'net_price'    => 37,
    },
);

#public methods

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

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

    my $currency_code;

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

    my $offsets = $fieldMap{$version};

    my $linenum = 1;
    foreach my $line (@$lines) {
        if ( $line->[ $offsets->{label} ] eq 'label-name' ) {

            if ( $version == 2 ) {
                my $currency_code_str = $line->[ $offsets->{unit_price} ];

                $currency_code_str =~ /([^-]+)-unit-price/;

                $currency_code = uc $1;
            }
            $linenum++;
            next;
        }

        # There may be sales with revenue but no units.
        my $counterFee = 0;

        my $service     = $line->[ $offsets->{service_id} ];
        my $serviceName = $line->[ $offsets->{service_name} ] if ( defined $offsets->{service_name} );
        my $prodtype    = $line->[ $offsets->{ptype} ];
        my $format      = $line->[ $offsets->{format} ];
        my $catno       = $line->[ $offsets->{catno} ];
        my $upc         = $line->[ $offsets->{upc} ];
        my $isrc        = $line->[ $offsets->{isrc} ];
        my $label       = $line->[ $offsets->{label} ];
        my $artist      = $line->[ $offsets->{artist} ];
        $artist = $line->[ $offsets->{album_artist} ] if ( $artist eq "" && $version == 6 );
        my $album     = $line->[ $offsets->{album} ];
        my $track     = $line->[ $offsets->{track} ];
        my $tracknum  = $line->[ $offsets->{tracknum} ];
        my $country   = $line->[ $offsets->{country} ];
        my $currency  = $line->[ $offsets->{currency} ];
        my $convrate  = $line->[ $offsets->{convrate} ];
        my $free      = $line->[ $offsets->{free} ] =~ /^(1|Y)$/ ? 1 : 0;
        my $units     = $line->[ $offsets->{units} ];
        my $price     = $line->[ $offsets->{price} ];
        my $ext_price = $line->[ $offsets->{ext_price} ];

        if ( ( $version == 1 ) && ( $units == 0 ) ) {
            $linenum++;
            next;
        }

        if ( !$price && $version == 1 && $units != 0 ) {
            $price = $ext_price / $units;
        } elsif ( !$price && $version == 1 && $units == 0 ) {
            $price = $ext_price;
        } elsif ( $version == 1 ) {
            $price /= $units;
        } else {

            # For a while the royalty report generator was reporting the dist-fee percentage
            # as a number between 0 and 100.  Two percent was written out as 2, although it
            # was stored correctly in the database as 0.02.
            #
            # Since we've been inconsistent with it, but the math always seems to have been correct
            # in the data, we'll just back into what the effective unit price. This only comes into
            # play as of version 2

            if ($units) {
                $price = $line->[ $offsets->{net_price} ] / $units;

                $price =~ s/^-0$/0/;

                $free = 1 if ( !$price );
            } else {

                # because we do some special handling for zero units later
                $price = $line->[ $offsets->{net_price} ];
            }
        }

        $country =
             $Common::Consts::COUNTRY_CODE{ lc( $line->[ $offsets->{country} ] ) }
          || $Common::Consts::COUNTRY_TO_CODE{ lc( $line->[ $offsets->{country} ] ) }
          if ( length( $line->[ $offsets->{country} ] ) > 2 );

        # We'll apply the conversion rate to the price, effectively converting
        # to USD.
        #
        if ( $convrate && $version == 1 ) {
            $price *= $convrate;
        }

        if ($currency_code) {
            $currency = $currency_code;
        }

        my ( $media_type, $fee );
        $media_type = $line->[ $offsets->{'media-type'} ] if ( $offsets->{'media-type'} );

        $counterFee = 1 if ( $units == 0 && $price != 0 );
        $units = 1 if ( $counterFee == 1 );
        $price *= -1 if ( $counterFee == 1 && $price < 0 );

        if ( $prodtype && ( $units != 0 || $price != 0 ) && $service ne "service-id" ) {
            my ( $dateBegin, $dateEnd ) = $self->_getDates( $line->[ $offsets->{start_date} ], $line->[ $offsets->{end_date} ] );

            unless ( $dateBegin && $dateEnd ) {
                $self->errstr("couldn't get dates");
                return undef;
            }

            if ( $service eq "" && defined $offsets->{service_name} && $serviceName ne "" ) {
                $service = $self->getServiceID($serviceName);
            }

            unless ( $service ne "" ) {
                $self->errstr( "Service ID not provided line:" . $linenum );
                print STDERR "No serviceID provided line:" . $linenum . "\n";
                return undef;
            }

            unless ( $country ne "" ) {
                $self->errstr( "Unknown country:" . $line->[ $offsets->{country} ] );
                print STDERR "Unknown country:" . $line->[ $offsets->{country} ] . "\n";
                return undef;
            }

            unless ( $format ne "" ) {
                $self->errstr( "No format provided: " . $line->[ $offsets->{format} ] . " line: " . $linenum );
                print STDERR "No format provided: " . $line->[ $offsets->{format} ] . " line: " . $linenum . "\n";
                return undef;
            }

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

            $sale->serviceID($service) if ( $service ne "" );
            $sale->productType($prodtype);
            $sale->formatType($format);
            $sale->dateBegin($dateBegin);
            $sale->dateEnd($dateEnd);
            $sale->clientProductID($catno);
            $sale->upc($upc);
            $sale->artistName($artist);
            $sale->albumName($album);
            $sale->labelName($label);

            if ( $prodtype eq RPS::File::Sale::TYPE_TRACK ) {
                $sale->trackName($track);
                $sale->trackNum($tracknum);
                $sale->isrc($isrc);
            }
            if ($media_type) {
                $sale->mediaType($media_type);
            }
            $sale->units($units);
            $sale->price($price);
            $sale->countryCode($country);
            $sale->currencyCode($currency);
            $sale->lineNum($linenum);
            $sale->free($free);

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

            if ( $counterFee == 1 ) {
                $price = 0;
                $units = -1;
                my $sale = RPS::Import::SaleRec->new();

                $sale->serviceID($service) if ( $service ne "" );
                $sale->productType($prodtype);
                $sale->formatType($format);
                $sale->dateBegin($dateBegin);
                $sale->dateEnd($dateEnd);
                $sale->clientProductID($catno);
                $sale->upc($upc);
                $sale->artistName($artist);
                $sale->albumName($album);
                $sale->labelName($label);

                if ( $prodtype eq RPS::File::Sale::TYPE_TRACK ) {
                    $sale->trackName($track);
                    $sale->trackNum($tracknum);
                    $sale->isrc($isrc);
                }
                if ($media_type) {
                    $sale->mediaType($media_type);
                }
                $sale->units($units);
                $sale->price($price);
                $sale->countryCode($country);
                $sale->currencyCode($currency);
                $sale->lineNum($linenum);
                $sale->free($free);

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

#else { print STDERR "Skip-> l:".$linenum ." pt: " .$prodtype." s: ".$service." u: ".$units." p: ".$price." ar: ".$artist." al: ".$album."<-Skip\n";}
        $linenum++;
    }
    return $linenum;
}

sub _getDates {
    my $self       = shift;
    my $start_date = shift;
    my $end_date   = shift;
    my ( $month_start, $month_end, $year_start, $year_end, $day_start, $day_end, $dateBegin, $dateEnd );

    # dates of the form yyyy-mm are allowed
    # in that case, set to first day of month for begin date
    # and last day of month for end date
    if ( $start_date =~ m/(\d{5})/ ) {
        ( $year_start, $month_start, $day_start ) = Add_Delta_Days( 1900, 1, 1, $1 - 2 );
    } elsif ( $start_date =~ m/(\d{4})\D(\d+)\D(\d+)/ ) {
        $month_start = $2;
        $year_start  = $1;
    } elsif ( $start_date =~ m/(\d+)\D(\d+)\D(\d{4})/ ) {
        $month_start = $1;
        $year_start  = $3;
    } elsif ( $start_date =~ m/(\d{4})\D(\d+)/ ) {
        $month_start = $2;
        $year_start  = $1;
    }
    if ( $end_date =~ m/(\d{5})/ ) {
        ( $year_end, $month_end, $day_end ) = Add_Delta_Days( 1900, 1, 1, $1 - 2 );
    } elsif ( $end_date =~ m/(\d{4})\D(\d+)\D(\d+)/ ) {
        $month_end = $2;
        $year_end  = $1;
    } elsif ( $end_date =~ m/(\d+)\D(\d+)\D(\d{4})/ ) {
        $month_end = $1;
        $year_end  = $3;
    } elsif ( $end_date =~ m/(\d{4})\D(\d+)/ ) {
        $month_end = $2;
        $year_end  = $1;
    }
    if ( $month_end && $year_end && $day_end && $month_start && $year_start && $day_start ) {
        $dateBegin = $year_start . "-" . $month_start . "-" . $day_start;
        $dateEnd   = $year_end . "-" . $month_end . "-" . $day_end;
        return ( $dateBegin, $dateEnd );
    } elsif ( $month_end && $year_end && $month_start && $year_start ) {
        $dateBegin = $year_start . "-" . $month_start . "-01";
        $dateEnd = $year_end . "-" . $month_end . "-" . Days_in_Month( $year_end, $month_end );
        return ( $dateBegin, $dateEnd );
    } else {
        print STDERR "Improper date format from: " . $dateBegin . "\n";
        $self->errstr( "Improper date format from: " . $dateBegin );
        print STDERR "Improper date end format from: " . $dateEnd . "\n";
        $self->errstr( "Improper date end format from: " . $dateEnd );
    }
    return undef;
}

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