package RPS::Import::PIAS::Combined::v2;

use strict;
use warnings;

use lib '/app/tools/common/lib';
use Common::Log;

use lib '/app/tools/rps/lib';
use RPS::Import::ServiceMap;
use Date::Calc qw(Days_in_Month Decode_Month);

use parent qw/RPS::Import::MapFaceBase RPS::Import::ImporterMixed/;

sub physical { 2 }

sub _fieldMapExtended {
    {
        mixed => {
            option1 => {
                serviceID    => 'F',
                countryCode  => 'E',
                dateBegin    => 'A6',
                dateEnd      => 'A6',
                productType  => 'G',
                formatType   => 'H',
                artistName   => 'A',
                upc          => 'D',
                albumName    => 'B',
                isrc         => 'C',
                trackName    => 'B',
                units        => 'P',
                currencyCode => 'A10',
                retailPrice  => 'K',
                totalRevenue => 'Q',
                price        => 'Q',
                priceLevel   => 'H',
                mediaType    => 'G',
            },
        },
    };
}

sub _unverifiedFieldMapExtended {
    {
        mixed => {
            option1 => {
                _netUnits => 'P',
            },
        },
    };
}

sub _headerIdentifierExtended {
    {
        mixed => {
            option1 => {
                artistName => 'ARTIST',
            },
        },
    };
}

sub currencyCode { shift->{_currencyCode} }
sub channel      { RPS::File::Sale::CHANNEL_RETAIL }

my %months = (
    'jan' => 1,
    'feb' => 2,
    'mar' => 3,
    'apr' => 4,
    'may' => 5,
    'jun' => 6,
    'jul' => 7,
    'aug' => 8,
    'sep' => 9,
    'oct' => 10,
    'nov' => 11,
    'dec' => 12,
);

sub _processSheet {
    my ($self, $sheet, $sheetnum) = @_;

    if ( $self->sheetname !~ /(?:Royalties|NR|PNR|Sheet\s?\d+)/i ) {
        Common::Log::Print("Skipping sheet '" . $self->sheetname . "'");
        return;
    }

    if ( $self->{_dateBegin} && $self->{_dateEnd} && $self->{_currencyCode} ) {
        return $self->SUPER::_processSheet( $sheet, $sheetnum );
    }

    if ( $self->sheetname() =~ /^(?:Royalties(?: ?\d.*)?|Sheet(?: ?\d.*)?|Summary)$/i ) {
        for my $i ( 0..50 ) {
            # we expect to get the start/end date values from A6, but the cell may be shifted
            my $dates = $sheet->[$i][0] || "";
            if ( $dates =~ /FOR PERIOD (\w{3}) (\d{4}) TO (\w{3}) (\d{4})/i ) {
                my ($startMonth, $startYear) = ($1, $2);
                my ($endMonth, $endYear) = ($3, $4);
                $self->{_dateBegin} = sprintf(
                    "%04d-%02d-%02d",
                    $startYear,
                    $months{ lc $startMonth },
                    1
                );
                $self->{_dateEnd} = sprintf(
                    "%04d-%02d-%02d",
                    $endYear,
                    $months{ lc $endMonth },
                    Days_in_Month( $endYear, $months{ lc $endMonth } )
                );
            }

            # we expect to get the currency from A10, but the cell may be shifted
            my $currency = $sheet->[$i][0] || "";
            if ( $currency =~ /^All amounts printed in (\w{3}).*$/i ) {
                $self->{_currencyCode} = $1;
            }
        }
    }

    return $self->SUPER::_processSheet( $sheet, $sheetnum );
}

sub saleDates {
    my $self = shift;

    # if we have cached dates
    if ( $self->{_dateBegin} && $self->{_dateEnd} ) {
        return ($self->{_dateBegin}, $self->{_dateEnd});
    }

    $self->fail("Unable to determine start/end dates");
}

sub serviceID {
    my $self = shift;

    my $service = lc( $self->_getByFieldName('serviceID') || '' );

    return Client::Service::DSP_NOKIA if $service =~ /^nokia\s/i;
    return Client::Service::DSP_CULTURA if $service =~ /^cultura[ .]/i;
    return Client::Service::DSP_LECLERC if $service =~ /espace (?:culturel|temps)/i;
    return Client::Service::DSP_LECLERC if $service =~ /leclerc/i;
    return Client::Service::DSP_LECLERC if $service =~ /^ec limoges \/ limoges dis$/i;
    return Client::Service::DSP_CONCERTO if $service =~ /^concerto b.v./i;
    return Client::Service::DSP_PIAS if $service =~ /^(?:uk exporter|label stock out)$/i;
    return Client::Service::DSP_PIAS if $service =~ /^fnac vanden borre -pias cd 50027-$/i;
    return Client::Service::DSP_NETFLIX if $service =~ /^trailer: les affam/i;
    return Client::Service::DSP_BOL if $service =~ /\(bol\.com\)/i;
    return Client::Service::DSP_MEDIA_MARKT if $service =~ /^media markt\s/i;
    return Client::Service::DSP_KROESE_COMPACT_DISCS if $service =~ /kroese/i;

    my @pias_list = ('artist sales','barometre / didier delages','beldis sas','brignoldis sas','cd & vinyl shop pick up',
                     'chaumondis sa','dinandis/espace musique','drukkerij b.v.','lp records','manhattan vinyle',
                     'non uk consignment stock','pias shop sprl','s.a.s trelidis','sa vierzon distribution','spirits',
                     'starter / corners music','trelidis sas','viennedis sas', 'medio europe bvba',
                     'uk consignment','33/45','communaute urbaine','dialogues musiques -sas loisirs',
                     'eirl camper disquaire cafe','personeel pias'
                     );
    return Client::Service::DSP_PIAS if grep { $service eq $_ } @pias_list;

    my $serviceID = $self->getServiceID($service) || $RPS::Import::ServiceMap::SERVICE_ALIASES{$service};
    return $serviceID if $serviceID;

    return Client::Service::DSP_PIAS unless $service;

    return $self->handleError( "Unknown service: '$service'", RPS::DB::Item::SaleImportError::kErrorService );
}

sub countryCode {
    my $self = shift;

    my $name = $self->_getByFieldName('countryCode') || '';
    my $oCountry = Common::Country->Get($name);
    if ( my $country = $oCountry->alpha2 ) {
        return $country;
    }

    $self->handleError( "Unknown country: '$name'.", RPS::DB::Item::SaleImportError::kErrorCountry );
    return $name;
}

sub productType {
    my $self = shift;

    my $type = $self->_getByFieldName('productType') || '';

    if ( $type =~ /^CD\s?(?:DIGIPACK|EP)?$/i ) {               # physical
        return RPS::File::Sale::TYPE_CD;
    } elsif ( $type =~ /^2?CD(?: LTD 2)?$/i ) {
        return RPS::File::Sale::TYPE_DBL_CD;
    } elsif ( $type =~ /^1?2(?:LTD|LP)?$/i ) {
        return RPS::File::Sale::TYPE_LP;
    } elsif ( $type =~ /^(?:2nd LP Format|LP LTD ED\.|LP \+ Download)$/i ) {
        return RPS::File::Sale::TYPE_LP;
    } elsif ( $type =~ /^12" EP$/i ) {
        return RPS::File::Sale::TYPE_LP5;
    } elsif ( $type =~ /^7$/i ) {
        return RPS::File::Sale::TYPE_LP5;
    } elsif ( $type =~ /^(?:[23]?LP|LP LTD ED\.|LP\s?\+\s?CD)$/i ) {
        return RPS::File::Sale::TYPE_LP;
    }  elsif ( $type =~ /^MC$/i ) {
        return RPS::File::Sale::TYPE_CASS;
    } elsif ( $type =~ /^Digital\s(?:Album|EP)(?: AV Bundle)?$/i ) {    # digital
        return RPS::File::Sale::TYPE_ALBUM;
    } elsif ( $type =~ /^Digital\s(?:Track|Single|VIDEO SHORT FORM)$/i ) {
        return RPS::File::Sale::TYPE_TRACK;
    } elsif ( $type =~ /^(?: ?Performer )?Neighbouring Rights$/i ) {
        return RPS::File::Sale::TYPE_TRACK;
    } elsif ( $type =~ /^(?:Third Party Compilation \(Royalties Only\)|SYNC)$/i ) {
        return $self->handleError( "Invalid format_type: '$type'", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
    }

    return $self->handleError( "Unable to determine product_type from: '$type'.", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
}

sub formatType {
    my $self = shift;

    if ( $self->sheetname =~ /^P?NR$/i ) {
        return RPS::File::Sale::FORMAT_PERFORMANCE;
    }

    my $service = $self->_getByFieldName('serviceID') || '';
    if ( $service =~ /Neighbouring Rights/i ) {
        return RPS::File::Sale::FORMAT_PERFORMANCE;
    }

    my $type = $self->_getByFieldName('formatType') || '';

    if ( $type =~ /^(?: A\sla\scarte\sdownload\sProduct | INVOICE )$/xi ) {
        return RPS::File::Sale::FORMAT_DOWNLOAD;
    } elsif ( $type =~ /^(?:
        Breakage | Cloud\sStreaming | Streaming | Official\sAd\-funded\sStreaming\sProduct |
        Radio\sstreaming\sproduct | Discount\ssubsc'\sstreaming\sproduct | Video\sCreation |
        Subsc'\s(?: Stream\sProd\s\(A\)|UGC\sproduct ) | Subscr'\sStreaming\sproduct )$/xi ) {
        return RPS::File::Sale::FORMAT_STREAM;
    } elsif ( $type =~ /^(?:Subscription DL Product|Subscr' Stream prod\(teth\))$/i ) {
        return RPS::File::Sale::FORMAT_TETHERED;
    } elsif ( $type =~ /^(?:Third Party License|Compilations|Compilation)$/i ) {
        return $self->handleError( "Invalid format_type: '$type'", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
    }

    return $self->handleError( "Unknown format_type: '$type'", RPS::DB::Item::SaleImportError::kErrorFormatType );
}

sub albumName {
    my $self = shift;

    if ( !$self->isDigitalProduct( $self->productType ) || $self->productType eq RPS::File::Sale::TYPE_ALBUM ) {
        return $self->_getByFieldName('albumName');
    }

    return;
}

sub trackName {
    my $self = shift;

    if ( $self->productType eq RPS::File::Sale::TYPE_TRACK ) {
        return $self->_getByFieldName('trackName');
    }

    return ;
}

sub isrc {
    my $self = shift;

    my $isrc = $self->_getByFieldName('isrc') || '';
    $isrc =~ s/-//g;

    return $isrc;
}

sub priceLevel {
    my $self = shift;

    my $level = $self->_getByFieldName('priceLevel') || '';

    if ( $level =~ /^ CREDIT\sNOTE | INVOICE $/xi ) {
        return RPS::File::Sale::PLEVEL_UNKNOWN;
    } elsif ( $level =~ /^ FULL\sPRICE $/xi ) {
        return RPS::File::Sale::PLEVEL_FULL;
    } elsif ( $level =~ /^MID PRICE$/i ) {
        return RPS::File::Sale::PLEVEL_MID;
    }

     $self->fail( "Unable to determine price_level from: '$level'." );
}

sub mediaType {
    my $self = shift;

    my $type = $self->_getByFieldName("mediaType") || '';
    if ( $type =~ /^ DIGITAL\sVIDEO\sSHORT\sFORM $/xi ) {
        return RPS::DB::Item::MediaType::kMediaTypeVideo;
    } elsif ( $type =~ /^(?: 2?CD\s?(?: DIGIPACK|EP|LTD\s2 )? | [23]?LP | Digital\s(?: Album|EP|Single|Track )?(?:\sAV\sBundle)? )$/xi ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    } elsif ( $type =~ /^(?:12|7)(LTD)?$/i ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    } elsif ( $type =~ /^(?:12" EP|MC|LP\s?\+\s?CD)$/i ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    } elsif ( $type =~ /^(?:2nd LP Format|LP LTD ED\.|LP \+ Download)$/i ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    } elsif ( $type =~ /^(?: Performer )?Neighbouring Rights$/i ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    }

    return $self->handleError( "Unknown media_type: '$type'", RPS::DB::Item::SaleImportError::kErrorMediaType );

}

sub price     { abs( shift->_getByFieldName('price') || 0 ) }
sub unitPrice { abs shift->SUPER::unitPrice }

sub units {
    my $self = shift;

    my $units = $self->_getByFieldName('units') || 0;
    my $price = $self->_getByFieldName('price') || 0;
    return $price < 0 ? abs($units) * -1 : $units;
}

# physical
sub netUnits       { $_[0]->_getByFieldName('_netUnits')              || 0 }
sub sales          { $_[0]->netUnits     > 0 ? $_[0]->netUnits         : 0 }
sub salesRevenue   { $_[0]->totalRevenue > 0 ? $_[0]->totalRevenue     : 0 }
sub returns        { $_[0]->netUnits     < 0 ? abs $_[0]->netUnits     : 0 }
sub returnsRevenue { $_[0]->totalRevenue < 0 ? abs $_[0]->totalRevenue : 0 }
sub totalRevenue {
    my $self = shift;
    my $revenue = $self->_getByFieldName('totalRevenue') || 0;
    return $revenue;
}

sub _isValidSaleRecord {

    return ( $_[0]->_getByFieldName('trackName') || $_[0]->_getByFieldName('albumName') )
    && ($_[0]->netUnits || $_[0]->totalRevenue);
}

# mapFace
sub _mapFaceProductType { }
sub _mapFaceServiceID   { 'serviceID' }
sub _mapFaceCountryCode { 'countryCode' }
sub _mapFaceFormatType  { 'formatType' }
sub _mapFaceMediaType   { 'mediaType' }


1;
