package RPS::Import::PIAS::Combined::v5;

use strict;
use warnings;
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 => 'A33',
                retailPrice  => 'K',
                totalRevenue => 'Q',
                price        => 'Q',
                priceLevel   => 'H',
                mediaType    => 'G',
            },
            option2 => {
                countryCode  => 'D',
                dateBegin    => 'G',
                dateEnd      => 'G',
                artistName   => 'C',
                isrc         => 'A',
                trackName    => 'B',
                units        => 'H',
                price        => 'I',
            },
        },
    };
}

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

sub _headerIdentifierExtended {
    {
        mixed => {
            option1 => {
                artistName => 'ARTIST',
            },
            option2 => {
                dateBegin => 'Sale Date',
            },
        },
    };
}

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

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

    if ($self->sheetname() ne "PNR") {
        # We need to grab date from A6
        my $dates = $sheet->[5]->[0] || "";

        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
        );

        #FOR PERIOD JAN 2020 TO JUN 2020
        $dates =~ /(\w{3}) (\d{4}) to (\w{3}) (\d{4})/i;
        $self->{_dateBegin} = sprintf( "%04d-%02d-%02d", $2, $months{$1}, 1 );
        $self->{_dateEnd}   = sprintf( "%04d-%02d-%02d", $4, $months{$3}, Days_in_Month($4, $months{$3}) );

        $self->{_currencyCode} = $self->_determineCurrency($sheet);
    }

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

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

    my $currency = 'GBP';

    # Getting currency from column A and row in range 0..99;
    my $col = 0;
    foreach my $row ( 0..99 ) {
        my $cellVal = $sheet->[$row][$col];
        if ( $cellVal =~ /^All amounts printed in (\w{3}).*/i ) {
            $currency = $1;
            last;
        }
    }

    return $currency
        ? $currency
        : $self->fail("Unable to determine currency code from column A");
}

sub saleDates {
    my $self = shift;

    if ($self->sheetname =~ /^PNR$/i) {
        my $date = $self->_getByFieldName("dateBegin");
        my ( $dateBegin, $dateEnd ) = $self->SUPER::_getDates( date_begin => $date, type => 'iso' );
        return ($dateBegin, $dateEnd) if ($dateBegin);
    }
    # 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_PIAS if $self->sheetname =~ /^PNR$/i;

    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;
    return Client::Service::DSP_TELMORE if $service =~ /telmore/i;
    return Client::Service::DSP_OCHRE if $service =~ /ochre/i;
    return Client::Service::DSP_SOUNDEXCHANGE if $service =~ /^Sound Exchange - Neighbouring Rights$/i;

    return Client::Service::DSP_UNKNOWN if $service =~ /ppl non qualifying performer share/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', '[pias] d2c physical', '[pias] d2c digital', '[pias] contintental physical sales'
                     );
    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;

    return RPS::File::Sale::TYPE_TRACK if $self->sheetname =~ /^PNR$/i;

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

    if ( $type =~ /^CD\s?(?:DIGIPACK|EP|BOX)?$/i ) {               # physical
        return RPS::File::Sale::TYPE_CD;
    } elsif ( $type =~ /^2?CD(?: LTD 2)?$/i || $type =~ /^(?:5 CD BOX)$/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 =~ /^(?:2?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)$/i ) {    # digital
        return RPS::File::Sale::TYPE_ALBUM;
    } elsif ( $type =~ /^Digital\s(?:Track|Single|VIDEO SHORT FORM)$/i ) {
        return RPS::File::Sale::TYPE_TRACK;
    }

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

sub formatType {
    my $self = shift;

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

    return RPS::File::Sale::FORMAT_PERFORMANCE if $service =~ /Neighbouring Rights/i;

    if ( $service =~ /^SoundExchange$/i || $self->sheetname =~ /^PNR$/i ) {
        return RPS::File::Sale::FORMAT_PERFORMANCE;
    }

    $self->fail("Unknown format_type '$type'") if ($type =~ /^(?:Compilations?|Third Party License)$/);

    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 |
        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;
    }

    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;

    return RPS::DB::Item::MediaType::kMediaTypeAudio if $self->sheetname =~ /^PNR$/i;

    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 )? | 2?LP | Digital\s(?: Album|EP|Single|Track )? )$/xi || $type =~ /^(?:5 CD BOX)$/i ) {
        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;
    }

    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;
