package RPS::Import::Tunecore::v2;

use strict;

use Math::BigFloat;

use lib '/app/tools/common/lib';
use lib '/app/tools/rps/lib';

use Common::Assert;
use Common::Country;
use RPS::Import::ServiceMap;

use base qw/RPS::Import::MapFaceBase RPS::Import::Importer/;

sub _fieldMap {
    {
        labelName   => 'I',
        serviceID   => 'C',
        countryCode => 'D',
        dateBegin   => 'A',
        dateEnd     => 'A',
        productType => 'F',
        formatType  => 'N',
        artistName  => 'E',
        upc         => 'J',
        albumName   => 'G',
        isrc        => 'M',
        trackName   => 'H',
        units       => 'O',
        price       => 'T',
    };
}

sub _unverifiedFieldMap {
    {
        optionalUPC => 'K',
        netSales    => 'Q',
        exchRate    => 'S',
        currency    => 'U',
    };
}

my %formatTypes = (
    'download'  => RPS::File::Sale::FORMAT_DOWNLOAD,
    'streaming' => RPS::File::Sale::FORMAT_STREAM,
);

sub _headerIdentifier { ( labelName => 'Label' ) }

sub currencyCode { shift->_getByFieldName("currency") }

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

    if ( $value && $value =~ /^(song|album)$/i ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    } elsif ( $value && $value =~ /^video$/i ) {
        return RPS::DB::Item::MediaType::kMediaTypeVideo;
    } elsif ( !$value ) {
        return RPS::DB::Item::MediaType::kMediaTypeAudio;
    }

    $self->fail("Unable to determine media type from '$value'");
}

sub upc {
    my $self = shift;

    # Use optionalUPC as primary, with upc as backup (FB10706).
    #
    my $upc = $self->_getByFieldName('optionalUPC');
    if ( !$upc || '' eq $upc ) {
        $upc = $self->_getByFieldName('upc');
    }
    return $upc;
}

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

    if ( $type && $type =~ /^album$/i ) {
        return RPS::File::Sale::TYPE_ALBUM;

    } elsif ( $type && $type =~ /^(song|video)$/i ) {
        return RPS::File::Sale::TYPE_TRACK;
    } elsif (!$type && $trackName ) {
        return RPS::File::Sale::TYPE_TRACK;
    } elsif (!$type && !$trackName ) {
        return RPS::File::Sale::TYPE_ALBUM;
    }

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

sub formatType {
    my $self  = shift;
    my $value = $self->_getByFieldName('formatType');

    my $formatType = $formatTypes{ lc($value) };

    $self->fail("Unknown format type '$value'") unless $formatType;

    return $formatType;
}

sub serviceID {
    my $self = shift;
    my $serviceID;
    my $service = $self->_getByFieldName('serviceID');

    if ($service) {
        my $serviceClean = $service;
        $serviceClean =~ s/ \(\w{2}\)//;
        $serviceID = $self->getServiceID($serviceClean) || $RPS::Import::ServiceMap::SERVICE_ALIASES{ lc $serviceClean };
    }

    return $serviceID if $serviceID;

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

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

    # The 'sign' of the units is driven by the price.
    # If the price is negative, we'll store negative units,
    # regardless of whether the units were positive or negative
    # in the sale file.  Accordingly, the price is always
    # positive.  This ensures that returns are recorded correctly.
    #
    if ( defined($price) ) {
        return $price < 0 ? abs($units) * -1 : $units;
    } else {
        return $units;
    }
}

sub unitPrice {
    return abs( shift->SUPER::unitPrice() );
}

sub countryCode {
    my $self = shift;

    my $country = $self->_getByFieldName('countryCode') || '';
    return 'US' if ($country eq 'WW');
    return 'KR' if ($country eq 'KO');

    my $code = Common::Country->Get($country);
    return $code->alpha2 if $code;

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

sub _validateSaleRec {
    my ( $self, $saleRec ) = @_;

    # Sanity check - was revenue actually converted for non-USD transactions?
    # but we need to make sure we're not calling this from the Mapper (after MapFace process)
    #
    if ((caller(1))[3] !~ /::Mapper/i) {
        my $currency = $self->_getByFieldName('currency');
        if ( $currency ne 'USD' ) {

            my $netSales = sprintf("%.8f", $self->_getByFieldName('netSales') || 0);
            my $price    = sprintf("%.8f", $self->_getByFieldName('price')    || 0);
            my $exchRate = $self->_getByFieldName('exchRate');
            if ( $netSales && $price && $netSales != $price ) {
                if ($exchRate) {
                    $netSales = $exchRate * $netSales;
                    my $allowableDiff = abs( $netSales - $price );
                    return 1 if $allowableDiff <= 0.1;
                }

                $self->fail("Revenue not converted");

            }
        }
    }

    return $self->SUPER::_validateSaleRec($saleRec);
}

sub _mapFaceProductType { }
sub _mapFaceServiceID   { 'serviceID' }
sub _mapFaceCountryCode { 'countryCode' }
sub _mapFaceFormatType  { }
sub _mapFaceMediaType   { }

1;
