package RPS::Import::Cadence;

use strict;
use warnings;

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

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

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

use parent 'RPS::Import::ImporterMixed';

my %productFormatMap = (
    'CMA RETURN DOWNLOAD (TRACK)'              => RPS::File::Sale::FORMAT_DOWNLOAD,
    'DIGITAL ONLINE AUD ALBUM PERMANENT'       => RPS::File::Sale::FORMAT_DOWNLOAD,
    'DIGITAL ONLINE AUD TRACK PERMANENT'       => RPS::File::Sale::FORMAT_DOWNLOAD,
    'DIGITAL ONLINE VID TRACK PERMANENT'       => RPS::File::Sale::FORMAT_DOWNLOAD,
    'DOWNLOAD (ALBUM)'                         => RPS::File::Sale::FORMAT_DOWNLOAD,
    'DOWNLOAD (TRACK)'                         => RPS::File::Sale::FORMAT_DOWNLOAD,
    'DOWNLOAD (VIDEO)'                         => RPS::File::Sale::FORMAT_DOWNLOAD,
    'DOWNLOAD (VIDEO DISC ON DEMAND)'          => RPS::File::Sale::FORMAT_DOWNLOAD,
    'PRE-ORDER DOWNLOAD (ALBUM)'               => RPS::File::Sale::FORMAT_DOWNLOAD,
    'RETURN CMA DOWNLOAD (TRACK)'              => RPS::File::Sale::FORMAT_DOWNLOAD,
    'RETURN DOWNLOAD (TRACK)'                  => RPS::File::Sale::FORMAT_DOWNLOAD,
    'RETURN DOWNLOAD (ALBUM)'                  => RPS::File::Sale::FORMAT_DOWNLOAD,
    'SU'                                       => RPS::File::Sale::FORMAT_STREAM,
    'SUBS'                                     => RPS::File::Sale::FORMAT_STREAM,
    'SUBSCR'                                   => RPS::File::Sale::FORMAT_STREAM,
    'SUPPORTED)'                               => RPS::File::Sale::FORMAT_STREAM,
    'VIDEO STREAMING (AD-SUPPORTED)'           => RPS::File::Sale::FORMAT_STREAM,
    'AUDIO TRACK STREAM WEBCAST'               => RPS::File::Sale::FORMAT_STREAM,
    'CMA DOWNLOAD (ALBUM)'                     => RPS::File::Sale::FORMAT_STREAM,
    'DIGITAL ALLOCATIONS DOWNLOADS'            => RPS::File::Sale::FORMAT_STREAM,
    'DIGITAL ONLINE AUD TRACK STREAM'          => RPS::File::Sale::FORMAT_STREAM,
    'DIGITAL ONLINE VID TRACK STREAM'          => RPS::File::Sale::FORMAT_STREAM,
    'STREAMING'                                => RPS::File::Sale::FORMAT_STREAM,
    'STREAMING (AD-SUPPORTED)'                 => RPS::File::Sale::FORMAT_STREAM,
    'STREAMING (CLOUD)'                        => RPS::File::Sale::FORMAT_STREAM,
    'STREAMING (FREE TRIAL)'                   => RPS::File::Sale::FORMAT_STREAM,
    'STREAMING (LOCKER)'                       => RPS::File::Sale::FORMAT_STREAM,
    'STREAMING (RADIO)'                        => RPS::File::Sale::FORMAT_STREAM,
    'STREAMING (SUBSCRIPTION)'                 => RPS::File::Sale::FORMAT_STREAM,
    'STREAMING (VIDEO)'                        => RPS::File::Sale::FORMAT_STREAM,
    'USER GENERATED CONTENT STREAM'            => RPS::File::Sale::FORMAT_STREAM,
    'VIDEO STREAM VIDEO PORTABLE'              => RPS::File::Sale::FORMAT_STREAM,
    'VIDEO STREAMING (MONETIZED)'              => RPS::File::Sale::FORMAT_STREAM,
    'VIDEO STREAMING (CLOUD)'                  => RPS::File::Sale::FORMAT_STREAM,
    'VIDEO STREAMING (FREE TRIAL)'             => RPS::File::Sale::FORMAT_STREAM,
    'VIDEO STREAMING (SUBSCRIPTION)'           => RPS::File::Sale::FORMAT_STREAM,
    'DIGITAL ALLOCATIONS STREAMS (AUDIO)'      => RPS::File::Sale::FORMAT_STREAM,
    'DIGITAL ALLOCATIONS STREAMS (VIDEO)'      => RPS::File::Sale::FORMAT_STREAM,
    'USER GENERATED CONTENT STREAM TRACK'      => RPS::File::Sale::FORMAT_STREAM,
    'DOWNLOAD (RENTAL)'                        => RPS::File::Sale::FORMAT_TETHERED,
    'STREAMING (JUKEBOX)'                      => RPS::File::Sale::FORMAT_JUKEBOX,
    'AUDIO TRACK STREAM WEBCAST PORTABLE'      => RPS::File::Sale::FORMAT_STREAM,
    'AUDIO SUBSCRIPTION TRUE UP'               => RPS::File::Sale::FORMAT_STREAM,
    'AUDIO SUBSCR'                             => RPS::File::Sale::FORMAT_STREAM,
    'SUBSCR LTDCAT'                            => RPS::File::Sale::FORMAT_STREAM,
    'USER GENERATED CONTENT STREAM VID SUBSCR' => RPS::File::Sale::FORMAT_STREAM,
    'AUDIO STREAM TRUE UP'                     => RPS::File::Sale::FORMAT_STREAM,
    'ORDER DOWNLOAD (ALBUM)'                   => RPS::File::Sale::FORMAT_DOWNLOAD,
);

my %productTypeMap = (
    physical => {
        "(CD+BOOKLET)" => RPS::File::Sale::TYPE_CD,
        "(2CD"         => RPS::File::Sale::TYPE_DBL_CD,
        "(2CD)"        => RPS::File::Sale::TYPE_DBL_CD,
        "(3CD"         => RPS::File::Sale::TYPE_DBL_CD,
        "(2CD+DVD)"    => RPS::File::Sale::TYPE_DVD_CD_SET,
        "(CD+DVD)"     => RPS::File::Sale::TYPE_DVD_CD_SET,
        "(2LP"         => RPS::File::Sale::TYPE_LP,
        "(2LP BLACK)"  => RPS::File::Sale::TYPE_LP,
        "(2LP)"        => RPS::File::Sale::TYPE_LP,
        "(2LP)"        => RPS::File::Sale::TYPE_LP,
        "(4LP)"        => RPS::File::Sale::TYPE_LP,
        "(LP+CD"       => RPS::File::Sale::TYPE_LP,
        "(LPX2)"       => RPS::File::Sale::TYPE_LP,
        "(LP+DVD)"     => RPS::File::Sale::TYPE_LP,
        "(DLX 4LP)"    => RPS::File::Sale::TYPE_LP,
        "(DLX LP)"     => RPS::File::Sale::TYPE_LP,
        "(DLX)"        => RPS::File::Sale::TYPE_LP,
        "(II)-LP"      => RPS::File::Sale::TYPE_LP,
        "(LP"          => RPS::File::Sale::TYPE_LP,
        "(LP)"         => RPS::File::Sale::TYPE_LP,
        "(7''LP"       => RPS::File::Sale::TYPE_LP5,
        '(LP+7""LP)'   => RPS::File::Sale::TYPE_LP5,
        "(LP+7''VYL"   => RPS::File::Sale::TYPE_LP5,
    },
    digital => {
        'A' => RPS::File::Sale::TYPE_ALBUM,
        'T' => RPS::File::Sale::TYPE_TRACK,
        'V' => RPS::File::Sale::TYPE_TRACK,
    },
);

# This is currently only being used to map the service ID back to Cadence.
my %serviceMap = (
    'AUDIO CLOUD SERVICES'                => 1234,
    'AUDIO CLOUD SERVICES'                => 1234,
    'AUDIO TRACK STREAM PORTABLE'         => 1234,
    'AUDIO TRACK STREAM WEBCAST'          => 1234,
    'AUDIO TRACK STREAM WEBCAST PORTABLE' => 1234,
    'DIGITAL ALLOCATIONS DOWNLOADS'       => 1234, ###
    'DIGITAL ALLOCATIONS STREAMS (AUDIO)' => 1234,
    'DIGITAL ALLOCATIONS STREAMS (VIDEO)' => 1234, ###
    'DIGITAL ONLINE AUD ALBUM PERMANENT'  => 1234,
    'DIGITAL ONLINE AUD TRACK PERMANENT'  => 1234,
    'DIGITAL ONLINE AUD TRACK STREAM'     => 1234,
    'DIGITAL ONLINE VID TRACK STREAM'     => 1234,
    'DIGITAL ONLINE VID TRACK PERMANENT'  => 1234,
    'USER GENERATED CONTENT STREAM'       => 1234,
    'VIDEO STREAM VIDEO PORTABLE'         => 1234,
    'VIDEO CLOUD SERVICES'                => 1234,
    'VIDEO STREAM WEBCASTING'             => 1234,
    'USER GENERATED CONTENT STREAM TRACK' => 1234, ###
);

sub physical { 2 }

sub _fieldMapExtended {
    {
        mixed => {
            option1 => {
                serviceID       => 'H',
                dateBegin       => 'A',
                dateEnd         => 'A',
                formatType      => 'H',
                clientProductID => 'I',
                artistName      => 'J',
                upc             => 'F',
                albumName       => 'K',
                isrc            => 'G',
                trackName       => 'D',
                units           => 'B',
                free            => 'H',
                totalRevenue    => 'C',
                price           => 'C',
                mediaType       => 'D',
            },
            option2 => {
                serviceID       => 'J',
                dateBegin       => 'A',
                dateEnd         => 'A',
                formatType      => 'J',
                clientProductID => 'N',
                artistName      => 'O',
                upc             => 'H',
                albumName       => 'P',
                isrc            => 'I',
                trackName       => 'F',
                sales           => 'B',
                salesRevenue    => 'C',
                returns         => 'D',
                returnsRevenue  => 'E',
                free            => 'J',
                mediaType       => 'F',
            },
        },
    };
}

sub _unverifiedFieldMapExtended {
    {
        mixed => {
            option1 => {
                _productTypePhys => 'K',
                _productTypeDig  => 'D',
                _netUnits        => 'B',
            },
            option2 => {
                _productTypePhys => 'P',
                _productTypeDig  => 'F',
            },
        },
    };
}

sub _headerIdentifierExtended {
    {
        mixed => {
            option1 => {
                isrc => 'isrc',
            },
            option2 => {
                isrc => 'isrc',
            },
        },
    };
}

sub countryCode  { 'CA' }
sub currencyCode { 'CAD' }
sub channel      { RPS::File::Sale::CHANNEL_RETAIL }
sub priceLevel   { RPS::File::Sale::PLEVEL_FULL }

sub productType {
    my $self = shift;

    my $trackName = $self->_getByFieldName('trackName') || '';
    my $free      = $self->_getByFieldName('free')      || '';

    my $type;
    # physical
    if ( !$trackName && !$free ) {
        $type = uc( $self->_getByFieldName('_productTypePhys') || '' );
        $type =~ s/.*(\(.*\)?).*$/$1/;

        return exists $productTypeMap{physical}{$type}
            ? $productTypeMap{physical}{$type}
            : RPS::File::Sale::TYPE_CD;
    }

    # digital
    if ( $trackName && $free ) {
        $type = uc( $self->_getByFieldName('_productTypeDig') || '' );
        $type =~ s/^\s*(\w).*/$1/;
        return $productTypeMap{digital}{$type} if exists $productTypeMap{digital}{$type};
    }

    $self->fail("Unknown product type: $type");
}

sub formatType {
    my $self = shift;

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

    # Quick check for SoundExchange first.
    if ( $type =~ /^SoundExchange - Streaming \(Radio\)$/i ) {
        return RPS::File::Sale::FORMAT_PERFORMANCE;
    }

    $type =~ s/^.*\s*-\s*(.*)$/$1/;
    return exists $productFormatMap{$type}
        ? $productFormatMap{$type}
        : $self->fail("Unknown format: $type");
}

sub saleDates {
    my $self = shift;

    my ($dateBegin, $dateEnd);
    my $dt = $self->_getByFieldName('dateBegin') || '';

    # YYYYMM
    if ( $dt =~ /^(\d{4})(\d{2})$/ ) {
        my ($year, $month) = ($1, $2);
        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $month, 1 );
        $dateEnd   = sprintf( "%04d-%02d-%02d", $year, $month, Days_in_Month( $year, $month ) );
    } else {
        ( $dateBegin, $dateEnd ) = $self->_getDates( date_begin => $dt );
    }

    return $dateBegin, $dateEnd;
}

sub albumName {
    my $self = shift;

    my $albumName = $self->_getByFieldName('albumName') || '';
    if ( $self->isDigitalProduct( $self->productType ) ) {
        return $albumName;
    }

    $albumName =~ s/^(.*)\s*\(.*$/$1/;
    return $albumName;
}

sub trackName {
    my $self = shift;

    my $trackName = $self->_getByFieldName('trackName') || '';
    if ( $trackName =~ /^T|V/i ) {
        $trackName =~ s/.* - (.*)/$1/;
        return $trackName;
    }

    return;
}

sub serviceID {
    my $self = shift;

    my $free = $self->_getByFieldName('free') || '';
    return Client::Service::DSP_CADENCE unless $free;

    my $serviceName = lc( $self->_getByFieldName('serviceID') || '');
    $serviceName =~ s/^(.*) - .*$/$1/;
    $serviceName =~ s/^\s+|\s+$//g;

    if (
           $serviceName =~ /^telco breakage/i
        || $serviceName =~ /^audio subscription true up/i
        || $serviceName =~ /^digital aud track stream/i
        || $serviceName =~ /^user generated content stream vid/i
        || $serviceName =~ /^audio stream true up/i
    ) {
      return Client::Service::DSP_CADENCE;
    }

    # First we'll see if we should just use the Cadence service ID.
    my $serviceID = $serviceMap{ uc $serviceName };
    return $serviceID if $serviceID;

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

    $self->fail("Unknown service: $serviceName");
}

sub free {
    my $self = shift;

    my $free  = $self->_getByFieldName('free')  || '';
    my $price = $self->dataTypeOption eq 'option2'
       ? $self->price
       : $self->_getByFieldName('price') || 0;

    return $price == 0 && $free =~ /free trial/i ? 1 : 0;
}


sub mediaType {
    my $self = shift;

    my $type = substr( $self->_getByFieldName('mediaType')  || '', 0, 1 );

    if ( !$type || $type =~ /^A|T$/i ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    } elsif ( $type =~ /^V$/i ) {
        return RPS::DB::Item::MediaType::kMediaTypeVideo;
    }

    $self->fail("Unknown media type: $type");
}

sub isrc {
    my $self = shift;
    my $isrc = $self->_getByFieldName('isrc') || '';
    $isrc =~ s/^#//;
    return $isrc;
}

# digital
sub unitPrice { abs shift->SUPER::unitPrice }

sub price     {
    my $self = shift;

    if ( $self->dataTypeOption eq 'option2' ) {
        my $salesRevenue   = $self->_getByFieldName('salesRevenue')   || 0;
        my $returnsRevenue = $self->_getByFieldName('returnsRevenue') || 0;
        return $salesRevenue + $returnsRevenue;
    }

    return $self->_getByFieldName('price') || 0;
}

sub units {
    my $self = shift;

    # RSD-3795
    if ( $self->dataTypeOption eq 'option2' ) {
        my $sales   = $self->_getByFieldName('sales')   || 0;
        my $returns = $self->_getByFieldName('returns') || 0;

        # RSD-3871 - was introduced after RSD-3795.
        my $salesRevenue   = $self->_getByFieldName('salesRevenue')   || 0;
        my $returnsRevenue = $self->_getByFieldName('returnsRevenue') || 0;
        if ( $sales && $salesRevenue && !$returns && !$returnsRevenue ) {
            return $salesRevenue < 0 ? -1 * abs $sales : abs $sales;
        } elsif ( !$sales && $returns && !$salesRevenue && $returnsRevenue ) {
            return $returnsRevenue < 0 ? -1 * abs $returns : abs $returns;
        }

        return $sales + $returns;
    }

    my $units = $self->_getByFieldName('units') || 0;
    my $price = $self->_getByFieldName('price') || 0;

    if ( $price < 0 && $units > 0 ) {
        $units = abs($units) * -1
    } elsif ( $price > 0 && $units < 0 ) {
        $units = abs($units);
    }

    return $units;
}

# physical
sub netUnits {
    my $self = shift;

    if ( $self->dataTypeOption eq 'option2' ) {
        my $sales   = $self->_getByFieldName('sales')   || 0;
        my $returns = $self->_getByFieldName('returns') || 0;
        return $sales + $returns;
    }

    return $self->_getByFieldName('_netUnits') || 0;
}

sub totalRevenue {
    my $self = shift;

    if ( $self->dataTypeOption eq 'option2' ) {
        my $salesRevenue   = $self->_getByFieldName('salesRevenue')   || 0;
        my $returnsRevenue = $self->_getByFieldName('returnsRevenue') || 0;
        return $salesRevenue + $returnsRevenue;
    }

    return $self->_getByFieldName('totalRevenue') || 0;
}

sub sales {
    my $self = shift;

    if ( $self->dataTypeOption eq 'option2' ) {
        my $sales = $self->_getByFieldName('sales') || 0;

        # add an extra unit depending on the revenue sign - an exception for this importer.
        return 1 if !$sales && $self->totalRevenue > 0;

        return $sales > 0 ? $sales : 0;
    }

    return $self->netUnits > 0 ? $self->netUnits : 0;
}

sub returns {
    my $self = shift;

    if ( $self->dataTypeOption eq 'option2' ) {
        my $sales   = $self->_getByFieldName('sales')   || 0;
        my $returns = $self->_getByFieldName('returns') || 0;

        # add an extra unit depending on the revenue sign - an exception for this importer.
        return 1 if !$sales && !$returns && $self->totalRevenue < 0;

        return $sales <= 0 ? abs $self->netUnits : abs $returns;
    }

    return $self->netUnits < 0 ? abs $self->netUnits : 0
}

sub salesRevenue {
    my $self = shift;

    if ( $self->dataTypeOption eq 'option2' ) {
        my $salesRevenue = $self->_getByFieldName('salesRevenue') || 0;
        return $salesRevenue > 0 ? $salesRevenue : 0;
    }

    $self->totalRevenue > 0 ? $self->totalRevenue : 0;
}

sub returnsRevenue {
    my $self = shift;

    if ( $self->dataTypeOption eq 'option2' ) {
        my $salesRevenue   = $self->_getByFieldName('salesRevenue')   || 0;
        my $returnsRevenue = $self->_getByFieldName('returnsRevenue') || 0;
        return $salesRevenue < 0 ? abs $self->totalRevenue : abs $returnsRevenue;
    }

    $self->totalRevenue < 0 ? abs $self->totalRevenue : 0
}

sub _isValidSaleRecord {

    if ( (!$_[0]->netUnits && !$_[0]->totalRevenue) || (!$_[0]->units && !$_[0]->price) ) {
        return 0;
    }

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


1;
