package RPS::Import::OrchardDigPhys;

use strict;
use warnings;

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

use lib '/app/tools/data_classes/lib';

use lib '/app/tools/rps/lib';
use RPS::Import::Importer;
use base 'RPS::Import::OrchardPub2';

sub physical { return 2; }    # A value of 2 means that this file could contain digital and/or physical sales.

sub _fieldMap {
    my $self = shift;

    my %fieldMap = (
        20 => {
            dateBegin        => 'B',
            serviceID        => 'C',
            countryCode      => 'D',
            upc              => 'F',
            serviceProductID => 'E',
            clientProductID  => 'G',
            labelName        => 'H',
            artistName       => 'I',
            albumName        => 'J',
            trackName        => 'K',
            isrc             => 'L',
            trackNum         => 'N',
            units            => 'O',
            formatType       => 'R',
            price            => 'U',
            currencyCode     => 'Z',
            wholesalePrice   => 'P',
            sales            => 'O',
            totalRevenue     => 'U',
        },
        22 => {    # similar to version 20, but different revenue and upc columns
            dateBegin        => 'B',
            serviceID        => 'C',
            countryCode      => 'D',
            upc              => 'F',
            serviceProductID => 'E',
            clientProductID  => 'G',
            labelName        => 'H',
            artistName       => 'I',
            albumName        => 'J',
            trackName        => 'K',
            isrc             => 'L',
            trackNum         => 'N',
            units            => 'O',
            formatType       => 'R',
            price            => 'AA',
            currencyCode     => 'Z',
            wholesalePrice   => 'P',
            sales            => 'O',
            totalRevenue     => 'AA',
        },
        24 => { # v24 has been moved to this dig/phys combined importer (RSD-673)
            labelName        => 'J',
            serviceID        => 'C',
            countryCode      => 'D',
            dateBegin        => 'B',
            dateEnd          => 'B',
            productType      => 'R',
            formatType       => 'R',
            clientProductID  => 'G',
            albumName        => 'L',
            isrc             => 'O',
            trackNum         => 'Q',
            trackName        => 'M',
            units            => 'W',
            currencyCode     => 'AF',
            price            => 'AA',
            wholesalePrice   => 'T',
            totalRevenue     => 'AA',
            mediaType        => 'R',
            sales            => 'W',
            serviceProductID => 'E',
            upc              => 'F',
            grossRevenue     => 'X',
        },
        25 => {
            dateBegin        => 'B',
            serviceID        => 'C',
            countryCode      => 'D',
            upc              => 'F',
            serviceProductID => 'E',
            clientProductID  => 'G',
            labelName        => 'I',
            artistName       => 'J',
            albumName        => 'K',
            trackName        => 'L',
            isrc             => 'N',
            trackNum         => 'P',
            units            => 'V',
            formatType       => 'Q',
            price            => 'Z',
            currencyCode     => 'AE',
            wholesalePrice   => 'S',
            sales            => 'V',
            totalRevenue     => 'Z',
            grossRevenue     => 'W',
        },
        26 => {
            labelName        => 'I',
            serviceID        => 'C',
            countryCode      => 'D',
            dateBegin        => 'B',
            dateEnd          => 'B',
            productType      => 'Q',
            formatType       => 'Q',
            clientProductID  => 'G',
            artistName       => 'J',
            upc              => 'F',
            serviceProductID => 'E',
            albumName        => 'K',
            isrc             => 'N',
            trackNum         => 'P',
            trackName        => 'L',
            units            => 'V',
            currencyCode     => 'AE',
            wholesalePrice   => 'S',
            sales            => 'V',
            totalRevenue     => 'AF',
            price            => 'AF',
            mediaType        => 'Q',
            grossRevenue     => 'W',
        },
        28 => {
            labelName        => 'I',
            serviceID        => 'C',
            countryCode      => 'D',
            dateBegin        => 'B',
            dateEnd          => 'B',
            productType      => 'Q',
            formatType       => 'Q',
            clientProductID  => 'G',
            artistName       => 'J',
            upc              => 'E',
            albumName        => 'K',
            isrc             => 'N',
            trackNum         => 'P',
            trackName        => 'L',
            units            => 'S',
            sales            => 'S',
            currencyCode     => 'U',
            totalRevenue     => 'T',
            price            => 'T',
            mediaType        => 'Q',
        },
    );

    return $fieldMap{ $self->_version() };
}

sub _unverifiedFieldMap {
    my $self = shift;

    my %fieldMap = (
        20 => {
            ringFee  => 'V',
            cloudFee => 'W',
            pubFee   => 'X',
            omsFee   => 'Y',
            adjGross => 'S',
        },
        22 => {
        },
        24 => {
            _artistName       => 'K',
            _trackArtist      => 'N',
            orchardUPC        => 'E',
            manufacturersUPC  => 'F',
            ringFee           => 'AB',    # ringtonePublishing
            cloudFee          => 'AC',    # cloudPublishing
            pubFee            => 'AD',    # publishing
            omsFee            => 'AE',    # mechAdministrativeFee
            _fatPossumRevenue => 'X',
            _fatPossumPrice   => 'X',
            _dateBeginAlt     => 'A',
            _dateEndAlt       => 'A',

        },
        25 => {
            trackArtist       => 'M',
            extraUPC          => 'E',
            ringFee           => 'AA',
            cloudFee          => 'AB',
            pubFee            => 'AC',
            omsFee            => 'AD',
            _fatPossumRevenue => 'W',
            _fatPossumPrice   => 'W',
        },
        26 => {
            trackArtist => 'M',
        },
        28 => {
            trackArtist => 'M',
        },
    );

    return $fieldMap{ $self->_version() };
}

sub serviceID {
    my $self = shift;

    return $self->_version == 26 && !$self->isDigitalProduct( $self->productType() )
        ? Client::Service::DSP_ORCHARD
        : $self->SUPER::serviceID;
}

sub countryCode {
    my $self = shift;

    my $country = $self->_getByFieldName('countryCode') || '';
    return 'CV' if $country =~ /^c.*ivoire$/i;

    return $self->SUPER::countryCode();
}

sub productType {
    my $self = shift;

    my $metalBladeProduct = $self->_metalBladeProductType();
    return $metalBladeProduct if $metalBladeProduct;

    my $_formatType = uc( $self->_getByFieldName('formatType') || '' );
    my $productName = $self->_getByFieldName('albumName') || '';

    if ($_formatType =~ /^PS|RE$/){
        return RPS::File::Sale::TYPE_LP if ($productName =~ /(?:2|3x)?LP(?: Reissue)?/i);
    }

    my $hMapping = $self->_getMappings($_formatType) || {};
    if ( exists $hMapping->{product_type} && $hMapping->{product_type} ) {
        my $trackNameFlag = $self->_getByFieldName('trackName') || '';

        # RSD-811 - if trackName is 'Full Album' then 'album' otherwise 'track'
        # RSD-9119 - Same for v25, v26, v28
        if ( $self->_version =~ /^(?:24|25|26|28)$/ && $_formatType eq 'DV' ) {
            return RPS::File::Sale::TYPE_TRACK if $trackNameFlag !~ /^Full Album$/i
        }

        # RSD-8889 - if Trans Type = 'SB' and trackName = 'Full Album' then 'album' otherwise 'track'
        # RSD-11573 - if Trans Type = SB and trackName = ‘Full Album’ or is blank, then ‘album’, otherwise ‘track’.
        if ( $_formatType eq 'SB' ) {
            if ( !$trackNameFlag || $trackNameFlag =~ /^Full Album$/i ) {
                return RPS::File::Sale::TYPE_ALBUM;
            } else {
                return RPS::File::Sale::TYPE_TRACK;
            }
        }

        return $hMapping->{product_type};
    }

    # Because this file format can include both digital and physical products
    # and other fields depend on us knowing if this one is physical or digital,
    # we must throw an error if the product type is not set.
    return $self->handleError(
        "Line #" . $self->linenum . ", product type not set for: '$_formatType'",
        RPS::DB::Item::SaleImportError::kErrorNonqualifying
    );
}

sub _metalBladeProductType {
    my $self = shift;

    # RSD-10999 - For only versions 24, 25, 26, 28 and only 4 clients
    return if $self->_version !~ /^(?:24|25|26|28)$/;
    return if (
        Common::RSApp::GetClientID() != Client::Client::kMetalBlade &&
        Common::RSApp::GetClientID() != Client::Client::kFatPossumRecords &&
        Common::RSApp::GetClientID() != Client::Client::kThrillerRecords &&
        Common::RSApp::GetClientID() != Client::Client::kMusicBrokers
    );

    my $serviceName = $self->_getByFieldName('serviceID') || '';
    return unless $serviceName =~ /youtube|facebook/i;

    my $albumName = $self->_getByFieldName('albumName') || '';
    return unless $albumName =~ /Youtube Exclusives/i;

    my $trackName = $self->_getByFieldName('trackName') || '';
    return if
           $trackName !~ /(?:FULL ALBUM|Limited Edition Double LP|LIVE DVD\/BLU-RAY|Slate Blue Vinyl|Split Vinyl|LP Stream|DVD)/i
        && $trackName !~ /(?:Album Stream|Official Album Stream|Album Teaser|Official Album Audio|Album Trailer|Full EP)/i;

    return RPS::File::Sale::TYPE_ALBUM;
}

sub albumName {
    my $self = shift;

    if ( my $name = $self->_metalBladeAlbumName() ) {
        return $name;
    }

    return $self->_getByFieldName('albumName');
}

sub _metalBladeAlbumName {
    my $self = shift;

    # RSD-10999 - For only versions 24, 25, 26, 28 and only 4 clients
    return if $self->_version !~ /^(?:24|25|26|28)$/;
    return if (
        Common::RSApp::GetClientID() != Client::Client::kMetalBlade &&
        Common::RSApp::GetClientID() != Client::Client::kFatPossumRecords &&
        Common::RSApp::GetClientID() != Client::Client::kThrillerRecords &&
        Common::RSApp::GetClientID() != Client::Client::kMusicBrokers
    );

    return if $self->productType ne RPS::File::Sale::TYPE_ALBUM;

    my $serviceName = $self->_getByFieldName('serviceID') || '';
    return unless $serviceName =~ /youtube|facebook/i;

    my $albumName = $self->_getByFieldName('albumName') || '';
    return unless $albumName =~ /Youtube Exclusives/i;

    my $trackName = $self->_getByFieldName('trackName') || '';
    return if
           $trackName !~ /(?:FULL ALBUM|Limited Edition Double LP|LIVE DVD\/BLU-RAY|Slate Blue Vinyl|Split Vinyl|LP Stream|DVD)/i
        && $trackName !~ /(?:Album Stream|Official Album Stream|Album Teaser|Official Album Audio|Album Trailer|Full EP)/i;

    return "YTE - $trackName";
}

sub mediaType {
    my $self = shift;

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

    my $mediaType;
    my $mapping = $self->_getMappings($_formatType);

    if ($mapping) {
        $mediaType = $mapping->{media_type};
    }

    if ($mediaType) {
        return $mediaType;
    } else {
        return $_formatType;
    }
}

sub upc {
    my $self = shift;

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

    if ( $self->_version == 24 ) {
        # digital
        if ( $self->isDigitalProduct( $self->productType() ) ) {
            return $self->_getByFieldName('orchardUPC');
        }
        # physical
        return $self->_getByFieldName('manufacturersUPC') || $self->_getByFieldName('orchardUPC');
    }

    if ( $self->_version == 25 ) {
        # digital
        if ( $self->isDigitalProduct( $self->productType() ) ) {
            return $self->_getByFieldName('extraUPC');
        }
        # physical
        return $self->_getByFieldName('upc') || $self->_getByFieldName('extraUPC');
    }

    return $upc || $self->_getByFieldName('serviceProductID');
}

sub artistName {
    my $self   = shift;

    return $self->SUPER::artistName() if $self->_version == 24;

    my $trackArtist = $self->_getByFieldName('trackArtist') || '';
    my $artistName  = $self->_getByFieldName('artistName')  || '';

    if ( $self->_version == 25 ) {
        my $isrc     = $self->_getByFieldName('isrc')     || '';
        my $extraUpc = $self->_getByFieldName('extraUPC') || '';
        return $isrc && $trackArtist && $isrc !~ /^\Q$extraUpc\E$/i
            ? $trackArtist
            : $artistName;
    }

    if ( $trackArtist && $self->productType() eq RPS::File::Sale::TYPE_TRACK ) {
        $artistName = $trackArtist;
    }

    return $artistName;
}

sub _isValidSaleRecord {
    my $self = shift;

    if ( $self->_version == 24 ) {
        return $self->_getByFieldName('trackName') || $self->_getByFieldName('albumName')  ? 1 : 0;
    }

    if ( $self->_version == 25 ) {
        return ( $self->_getByFieldName('units') || $self->_getByFieldName('sales') ) ? 1 : 0;
    }

    return ( $self->upc || $self->isrc ) && ( $self->trackName || $self->albumName );
}

################## Digital-only Fields #####################################

sub units {
    my $self = shift;

    return unless RPS::Import::Importer->isDigitalProduct( $self->productType() );

    my $price = $self->price();
    my $units = $self->_getByFieldName('units') || 0;
    my ($numFormat) = $self->filename =~ /_(EU|US)/;
    $numFormat ||= "US";

    # Allowing dot (.) in US formatted sales files. RSD-8135
    $units = $1 if ($numFormat eq "US" && $units =~ /^(-?\d+)\.0+$/);

    $self->fail("Units '$units' in non-integer format.") if ($units =~ /(,.*)+\./ || $units =~ /(\..*)+,/ || $units =~ /^0[.,]/);
    $self->fail("Units '$units' in non-integer format for EU region") if ($units =~ /,/ && $numFormat eq 'EU');
    $self->fail("Units '$units' in non-integer format for US region") if ($units =~ /\./ && $numFormat eq 'US');
    $units =~ s/[.,]//g;

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

    return $units;
}

sub price {
    my $self = shift;

    if ( RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        my $price = $self->_getByFieldName('price');
        $price =~ s/\$//g;
        $price =~ s/,//g;

        # If the template doesn't have the ring/cloud/pub/oms fields, then
        # default them to zero.
        #
        my $ringFee  = ( defined $self->_getByFieldName('ringFee') )  ? $self->_getByFieldName('ringFee')  : 0;
        my $cloudFee = ( defined $self->_getByFieldName('cloudFee') ) ? $self->_getByFieldName('cloudFee') : 0;
        my $pubFee   = ( defined $self->_getByFieldName('pubFee') )   ? $self->_getByFieldName('pubFee')   : 0;
        my $omsFee   = ( defined $self->_getByFieldName('omsFee') )   ? $self->_getByFieldName('omsFee')   : 0;

        # Look at the adjusted gross if no revenue reported
        #
        my $adjGross = ( defined $self->_getByFieldName('adjGross') ) ? $self->_getByFieldName('adjGross') : 0;
        $price = $adjGross if ( !defined $price || $price == 0 );

        $ringFee =~ s/\$//g;
        $cloudFee =~ s/\$//g;
        $pubFee =~ s/\$//g;
        $omsFee =~ s/\$//g;

        if ( $self->_version == 25 ) {
            $price = $price + $ringFee + $cloudFee + $pubFee + $omsFee;
            if ( Common::RSApp::GetClientID() == Client::Client::kFatPossumRecords && $self->filename =~ /house.arrest/i ) {
                my $fatPossumPrice = $self->_getByFieldName('_fatPossumPrice') || 0;
                $fatPossumPrice =~ s/[,\$]//g;

                $price = $fatPossumPrice + $ringFee + $cloudFee + $pubFee + $omsFee;
            }
        } elsif ( $self->_version == 24 ) {
            $price = $self->_getByFieldName('price') || 0;
            $price =~ s/\$//g;
            $price =~ s/,//g;

            $price = $price + $ringFee + $cloudFee + $pubFee + $omsFee;

            if ( Common::RSApp::GetClientID() == Client::Client::kFatPossumRecords && $self->filename =~ /house.arrest/i ) {
                my $fatPossumPrice = $self->_getByFieldName('_fatPossumPrice') || 0;
                $fatPossumPrice =~ s/[,\$]//g;

                $price = $fatPossumPrice + $ringFee + $cloudFee + $pubFee + $omsFee;
            }
        } else {
            $ringFee  *= -1 if ( $ringFee < 0 );
            $cloudFee *= -1 if ( $cloudFee < 0 );
            $pubFee   *= -1 if ( $pubFee < 0 );
            $omsFee   *= -1 if ( $omsFee < 0 );
            $price = $price - $ringFee - $cloudFee - $pubFee - $omsFee;
        }

        return $price;
    }
}

sub trackNum {
    my $self = shift;

    if ( RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        return $self->_getByFieldName('trackNum');
    } else {
        return undef;
    }
}

sub serviceProductID {
    my $self = shift;

    if ( RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        return $self->_getByFieldName('serviceProductID');
    } else {
        return undef;
    }
}

sub formatType {
    my $self = shift;

    if ( RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {

        # RSD-11462
        if ( $self->serviceID == Client::Service::DSP_SOUNDEXCHANGE ) {
            return RPS::File::Sale::FORMAT_NON_EPHEMERAL;
        }

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

        if ($self->_version == 25 && Common::RSApp::GetClientID() == Client::Client::kExpandedMusic) {
            my $service = $self->_getByFieldName('serviceID') || '';
            return RPS::File::Sale::FORMAT_SYNC if ( $service =~ /youtube/i)
        }

        if ( $self->_version == 26 && $_formatType eq 'RB' ) {
            return RPS::File::Sale::FORMAT_RINGTONE;
        }

        my $formatType;
        my $mapping = $self->_getMappings($_formatType);

        if ($mapping) {
            $formatType = $mapping->{format_type};
        }

        if ($formatType) {
            return $formatType;
        } else {
            return $_formatType;
        }
    }
}

################## Physical-only Fields #####################################

sub channel {
    my $self = shift;

    if ( !RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        return RPS::File::Sale::CHANNEL_RETAIL;
    }
}

sub priceLevel {
    my $self = shift;

    if ( !RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        return RPS::File::Sale::PLEVEL_UNKNOWN;
    }
}

sub wholesalePrice {
    my $self = shift;

    if ( !RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        return $self->_getByFieldName('wholesalePrice');
    }
}

sub sales {
    my $self = shift;

    if ( !RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        if ( $self->totalRevenue >= 0 ) {
            my $sales = $self->_getByFieldName('sales');
            $sales =~ s/,//g;
            return abs( $sales );
        }
    }
}

sub salesRevenue {
    my $self = shift;

    if ( !RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        if ( $self->totalRevenue > 0 ) {
            return abs( $self->totalRevenue );
        }
    }
}

sub returns {
    my $self = shift;

    if ( !RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        if ( $self->totalRevenue < 0 ) {
            my $sales = $self->_getByFieldName('sales');
            $sales =~ s/,//g;
            return abs( $sales );
        }
    }
}

sub grossRevenue {
    my $self = shift;

    my $grossRevenue = $self->_getByFieldName('grossRevenue') || 0;
    $grossRevenue =~ s/,//g;
    return $grossRevenue;
}

sub returnsRevenue {
    my $self = shift;

    if ( !RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        if ( $self->totalRevenue < 0 ) {
            return abs( $self->totalRevenue );
        }
    }
}

sub totalRevenue {
    my $self = shift;

    if ( !RPS::Import::Importer->isDigitalProduct( $self->productType() ) ) {
        my $revenue = $self->_getByFieldName('totalRevenue');
        $revenue =~ s/,//g;

        if ( $self->_version =~ /(?:24|25)/ ) {
            my $ringFee  = $self->_getByFieldName('ringFee')  || 0;
            my $cloudFee = $self->_getByFieldName('cloudFee') || 0;
            my $pubFee   = $self->_getByFieldName('pubFee')   || 0;
            my $omsFee   = $self->_getByFieldName('omsFee')   || 0;
            $_ =~ s/,//g for ($ringFee, $cloudFee, $pubFee, $omsFee);
            $revenue += $ringFee + $cloudFee + $pubFee + $omsFee;

            if ( Common::RSApp::GetClientID() == Client::Client::kFatPossumRecords && $self->filename =~ /house.arrest/i ) {
                my $fatPossumRevenue = $self->_getByFieldName('_fatPossumRevenue') || 0;
                $fatPossumRevenue =~ s/,//g;

                $revenue = $fatPossumRevenue + $ringFee + $cloudFee + $pubFee + $omsFee;
            }
        }

        return $revenue;
    }
}

###
1;    # Play nicely.
###
