package RPS::Import::Caroline::v26;

use strict;
use warnings;

use lib '/app/tools/rps/lib';
use lib '/app/tools/data_classes/lib';
use RPS::File::Sale;
use RPS::Import::ServiceMap;
use RPS::DB::Item::MediaType;
use Common::UTF8;

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

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

sub physical { 2 }

sub _fieldMapExtended {
    {
        mixed => {
            option1 => {
                # Physical
                labelName      => 'A',
                countryCode    => 'J',
                dateBegin      => 'K',
                dateEnd        => 'K',
                productType    => 'F',
                artistName     => 'C',
                upc            => 'G',
                albumName      => 'D',
                retail         => 'O',
                sales          => 'L',
                salesRevenue   => 'R',
                returns        => 'M',
                returnsRevenue => 'U',
                units          => 'N',
                totalRevenue   => 'AD',
                mediaType      => 'F',
            },
            option2 => {
                # Digital
                dateBegin   => 'K',
                dateEnd     => 'K',
                artistName  => 'C',
                countryCode => 'J',
                albumName   => 'B',
                units       => 'P',
                trackName   => 'D',
                upc         => 'F',
                isrc        => 'G',
                price       => 'W',
                serviceID   => 'H',
                productType => 'E',
            }
        },
    };
}

sub _unverifiedFieldMapExtended {
    {
        mixed => {
            option1 => {
                # Physical
                discount  => 'X',
                dist_fee  => 'AB',
                netUnits  => 'N',
                returnFee => 'AA',
            },
            option2 => {
                # Digital
                deliveryFormat => 'M',
                deliveryType   => 'L',
                releaseType    => 'E',
                releaseTitle   => 'D',
                netUnits       => 'P',
            }
        }
    };
}

sub _headerIdentifierExtended {
    {
        mixed => {
            option1 => { productType => 'Media Type' },
            option2 => { isrc => 'ISRC' }
        },
    };
}

my %formatMediaMap = (
    'Streams Sales' => {
        'Ad-funded portable webcasting' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Cached Plays' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Ephemeral Play' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Fixed Plays' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Hard bundled subscription plays' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Permanent Download (Subscription)' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Play / Stream (B2B)' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Play / Stream (Free Service)' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Play / Stream (Subscr.)' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Play / Stream (Webcasting)' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Play / Stream Portable (Subscr.)' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Play / Stream subscription via mobile application' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Premium Webcasting' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Programmed Streaming (non-royalty bearing)' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Soft bundled subscription plays' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Subscription Webcasting' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'User Generated Content Stream' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'User Generated Content Stream(Subscr)' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Digital Allocations Download' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Digital Allocations Streaming' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Digital Allocations Telco Breakage' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Play / Stream (Subscr. Limited Catalogue)' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Temporary download' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Sponsorship Stream' => {
            format_type => RPS::File::Sale::FORMAT_STREAM,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        }
    },
    'Download' => {
        'Kiosk' => {
            format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Permanent Download (burnable)' => {
            format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        },
        'Rental' => {
            format_type => RPS::File::Sale::FORMAT_DOWNLOAD,
            media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio,
        }
    }
);

my %productMediaMap = (
    'Track' => {
        product_type => RPS::File::Sale::TYPE_TRACK
    },
    'eSingle Audio/Multi Track' => {
        product_type => RPS::File::Sale::TYPE_ALBUM
    },
    'Album' => {
        product_type => RPS::File::Sale::TYPE_ALBUM,
    },
    'Single' => {
        product_type => RPS::File::Sale::TYPE_TRACK,
    },
    'Vinyl' => {
        product_type => RPS::File::Sale::TYPE_LP,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio
    },
    'CD' => {
        product_type => RPS::File::Sale::TYPE_CD,
        media_type   => RPS::DB::Item::MediaType::kMediaTypeAudio
    }

);

my %months   = (
    January   => '01',
    February  => '02',
    March     => '03',
    April     => '04',
    May       => '05',
    June      => '06',
    July      => '07',
    August    => '08',
    September => '09',
    October   => '10',
    November  => '11',
    December  => '12',
);

sub currencyCode { 'EUR' }
sub priceLevel   { RPS::File::Sale::PLEVEL_UNKNOWN }

sub serviceID {
    my $self = shift;

    if ( $self->isDigitalProduct( $self->productType() ) ) {
        # Digital
        my $service = lc( $self->_getByFieldName('serviceID') || '' );

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

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

    #Physical
    return Client::Service::DSP_CAROLINE;
}

sub countryCode   {
    my $self = shift;

    my $name = $self->_getByFieldName('countryCode') || '';
    my $oCountry = Common::Country->Get($name);

    my $countryCode = $oCountry->alpha2 if $oCountry;
    return $countryCode if $countryCode;

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

sub saleDates {
    my $self = shift;

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

    if ( $dateBegin =~ /^(\d{4})-?(\d{1,2})$/ ) {
        # Digital
        $dateBegin = sprintf( "%04d-%02d-%02d", $1, $2, "1" );
        $dateEnd = sprintf( "%04d-%02d-%02d", $1, $2, Days_in_Month($1, $2) );
    }
    elsif ( $dateBegin =~ /^(\w+)\s(\d{2})$/ ) {
        # Physical
        return if ( !exists $months{$1} );
        my $year = "20" . $2;
        $dateBegin = sprintf( "%04d-%02d-%02d", $year, $months{$1}, "1" );
        $dateEnd = sprintf( "%04d-%02d-%02d", $year,  $months{$1}, Days_in_Month($year, $months{$1}) );
    }

    return ($dateBegin, $dateEnd);
}

sub productType {
    my $self = shift;

    my $type = $self->_getByFieldName('productType') || "";
    return $productMediaMap{$type}->{product_type} if ( exists $productMediaMap{$type} );

    return $self->handleError(
        "Product type not set: $type",
        RPS::DB::Item::SaleImportError::kErrorNonqualifying
    );
}

sub formatType {
    my $self = shift;

    my $deliveryType = $self->_getByFieldName('deliveryType') || '';
    my $deliveryFormat = $self->_getByFieldName('deliveryFormat') || '';

    if ( exists($formatMediaMap{$deliveryType}) && exists($formatMediaMap{$deliveryType}->{$deliveryFormat}) ){
        return $formatMediaMap{$deliveryType}->{$deliveryFormat}->{format_type};
    }

    if ( $deliveryFormat =~ /mobile images/i ) {
        return $self->handleError( "Unsupported format_type '$deliveryFormat'", RPS::DB::Item::SaleImportError::kErrorNonqualifying );
    }

    return $self->handleError(
        "Couldn't determine product format for configuration '$deliveryType', '$deliveryFormat': ",
        RPS::DB::Item::SaleImportError::kErrorFormatType
    );
}

sub mediaType {
    my $self = shift;

    my $deliveryType = Common::UTF8::ToAscii($self->_getByFieldName('deliveryType') || '');
    my $deliveryFormat = Common::UTF8::ToAscii($self->_getByFieldName('deliveryFormat') || '');

    unless ($self->isDigitalProduct( $self->productType )) {
        # Physical
        my $type = $self->_getByFieldName('mediaType') || "";
        return $productMediaMap{$type}->{media_type} if (exists $productMediaMap{$type} && exists $productMediaMap{$type}->{media_type});
    }
    if ( exists($formatMediaMap{$deliveryType}) && exists($formatMediaMap{$deliveryType}->{$deliveryFormat}) ){
        return $formatMediaMap{$deliveryType}->{$deliveryFormat}->{media_type};
    }

    return $self->handleError(
        "Media type not set for configuration: '$deliveryType', '$deliveryFormat'",
        RPS::DB::Item::SaleImportError::kErrorMediaType
    );
}

sub upc {
    my $self = shift;

    my $isDigitalProduct = $self->isDigitalProduct( $self->productType );
    return !$isDigitalProduct || $self->productType eq RPS::File::Sale::TYPE_ALBUM
        ? $self->_getByFieldName('upc')
        : undef;
}

sub isrc {
    my $self = shift;
    my $type = $self->productType || "";

    return $type eq RPS::File::Sale::TYPE_TRACK
        ? $self->_getByFieldName('isrc')
        : undef;
}

sub trackName {
    my $self = shift;
    my $type = $self->productType || "";

    return $type eq RPS::File::Sale::TYPE_TRACK
        ? $self->_getByFieldName('trackName')
        : undef;
}

sub channel {
    return RPS::File::Sale::CHANNEL_RETAIL;
}

sub wholesalePrice {
    my $self = shift;

    my $salesRevenue = $self->_getByFieldName('salesRevenue') || 0;
    my $discount    = $self->_getByFieldName('discount') || 0;

    return sprintf "%.8f", $salesRevenue * ( 1 - $discount );
}

sub salesRevenue {
    my $self = shift;

    my $salesRevenue = $self->_getByFieldName('salesRevenue') || 0;
    my $distFee      = $self->_getByFieldName('dist_fee')     || 0;

    # sometimes sales and returns are switched. need to handle this correctly
    if ( $self->_getByFieldName('sales') < 0 ) {
        $salesRevenue = $self->_getByFieldName('returnsRevenue') || 0;
    }

    $salesRevenue = sprintf "%.8f", $salesRevenue * (1 - $distFee);

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

sub returnsRevenue {
    my $self = shift;

    my $returnsRevenue = $self->_getByFieldName('returnsRevenue') || 0;
    my $distFee        = $self->_getByFieldName('dist_fee')       || 0;
    my $returnFee      = $self->_getByFieldName('returnFee')      || 0;

    # sometimes sales and returns are switched. need to handle this correctly
    if ( $self->_getByFieldName('sales') < 0 ) {
        $returnsRevenue = $self->_getByFieldName('salesRevenue') || 0;
        $returnFee = 0;
    }

    $returnsRevenue = sprintf "%.8f", $returnsRevenue * (1 - $distFee) + $returnFee;

    return $returnsRevenue < 0 ? abs($returnsRevenue) : 0;
}

sub units {
    my $self = shift;
    my $units = $self->netUnits;
    my $price = $self->_getByFieldName('price') || 0;

    return $units if $price == 0;
    return $price < 0 ? abs($units) * -1 : abs($units);
}


sub netUnits       { sprintf "%.0f", ( shift->_getByFieldName('netUnits') || 0 ) }
sub totalRevenue   { $_[0]->_getByFieldName('totalRevenue')               || 0 }
sub sales          { $_[0]->netUnits     > 0 ? $_[0]->netUnits         : 0 }
sub returns        { $_[0]->netUnits     < 0 ? abs $_[0]->netUnits     : 0 }

sub _isValidSaleRecord {
    my $self = shift;
    my $productType = $self->_getByFieldName('productType');

    unless ($productType && $self->isDigitalProduct($self->productType())) {
        # Physical
        if ($self->netUnits == 0 && ($self->totalRevenue != 0)) {
            $self->fail("ERROR while processing physical sale record. Units = 0 and Revenue IS NOT 0")
        }
    }

    return defined $self->netUnits
        && ( defined $self->totalRevenue || defined $self->_getByFieldName('price') )
        && ( $self->_getByFieldName('albumName') || $self->_getByFieldName('trackName') );
}

sub _mapFaceServiceID   { 'serviceID' }
sub _mapFaceCountryCode { 'countryCode' }
sub _mapFaceProductType { 'releaseType' }
sub _mapFaceFormatType  { 'deliveryType', 'deliveryFormat' }
sub _mapFaceMediaType   { 'deliveryType', 'deliveryFormat' }

1;
