package RPS::Import::Melodic::v1;

use strict;
use warnings;
use utf8;
use POSIX qw/ceil/;

use lib '/app/tools/rps/lib';
use Date::Calc qw(Days_in_Month Add_Delta_Days Decode_Month);
use RPS::Import::ServiceMap;

use parent qw/RPS::Import::MapFaceBase RPS::Import::ImporterMixed/;

sub physical {
    my $self = shift;
    return 2;
}

my %sheetMap = (
    'itunes'                         => ['digital',  'option1'],
    'apple music'                    => ['digital',  'option2'],
    'beats radio'                    => ['digital',  'option3'],
    'beats radio alternative'        => ['digital',  'option4'],
    'srd digital'                    => ['digital',  'option5'],
    'itunes alternative'             => ['digital',  'option6'],

    'srd sales'                      => ['physical', 'option1'],  # old format
    'morr music'                     => ['physical', 'option2'],
    'labaleine'                      => ['physical', 'option3'],
    'bigwax'                         => ['physical', 'option4'],
    'srd sales alternative'          => ['physical', 'option5'],  # new format
);

sub _fieldMapExtended {
    {
        digital => {
            option1 => {    # iTUNES
                labelName        => 'R',
                countryCode      => 'V',
                productType      => 'T',
                formatType       => 'T',
                serviceProductID => 'O',
                artistName       => 'P',
                upc              => 'C',
                albumName        => 'Q',
                isrc             => 'D',
                trackName        => 'Q',
                units            => 'F',
                price            => 'M',
                mediaType        => 'T',
            },
            option2 => {    # Apple Music
                labelName        => 'S',
                countryCode      => 'A',
                serviceProductID => 'B',
                artistName       => 'N',
                isrc             => 'L',
                trackName        => 'M',
                units            => 'D',
                price            => 'J',
                mediaType        => 'P',
            },
            option3 => {    # Beats Radio (main, with the 'Currency' column)
                labelName        => 'O',
                countryCode      => 'A',
                serviceProductID => 'B',
                artistName       => 'E',
                isrc             => 'C',
                trackName        => 'D',
                units            => 'F',
                price            => 'M',
            },
            option4 => {    # Beats Radio (alternative, w/o the 'Currency' column)
                labelName        => 'N',
                countryCode      => 'A',
                serviceProductID => 'B',
                artistName       => 'E',
                isrc             => 'C',
                trackName        => 'D',
                units            => 'F',
                price            => 'L',
            },
            option5 => {    # SRD Digital (can contain a digit at the very end of the name)
                labelName        => 'A',
                serviceID        => 'J',
                countryCode      => 'K',
                productType      => 'E',
                formatType       => 'L',
                artistName       => 'C',
                upc              => 'F',
                albumName        => 'D',
                isrc             => 'G',
                trackName        => 'D',
                units            => 'R',
                price            => 'Z',
                mediaType        => 'L',
            },
            option6 => {    # iTUNES alternative
                labelName        => 'R',
                countryCode      => 'V',
                productType      => 'T',
                formatType       => 'T',
                serviceProductID => 'O',
                artistName       => 'P',
                upc              => 'C',
                albumName        => 'Q',
                isrc             => 'D',
                trackName        => 'Q',
                units            => 'F',
                price            => 'L',
                mediaType        => 'T',
            },
        },
        physical => {
            option1 => {    # SRD Sales OLD FORMAT
                labelName       => 'B',
                countryCode     => 'E',
                dateBegin       => 'F',
                dateEnd         => 'F',
                productType     => 'K',
                clientProductID => 'G',
                artistName      => 'I',
                albumName       => 'J',
                wholesalePrice  => 'H',
                sales           => 'M',
                salesRevenue    => 'N',
                returns         => 'M',
                returnsRevenue  => 'N',
                totalRevenue    => 'S',
                mediaType       => 'K',
            },
            option2 => {    # Morr Music
                productType     => 'D',
                clientProductID => 'A',
                artistName      => 'B',
                albumName       => 'C',
                sales           => 'F',
                salesRevenue    => 'I',
                returns         => 'F',
                returnsRevenue  => 'I',
                totalRevenue    => 'K',
                mediaType       => 'D',
            },
            option3 => {    # Labaleine
                labelName       => 'D',
                productType     => 'E',
                clientProductID => 'A',
                artistName      => 'B',
                albumName       => 'C',
                wholesalePrice  => 'G',
                sales           => 'F',
                salesRevenue    => 'J',
                returns         => 'F',
                returnsRevenue  => 'J',
                totalRevenue    => 'L',
                mediaType       => 'E',
            },
            option4 => {    # Bigwax
                labelName       => 'D',
                productType     => 'E',
                clientProductID => 'A',
                artistName      => 'B',
                albumName       => 'C',
                wholesalePrice  => 'G',
                sales           => 'F',
                salesRevenue    => 'J',
                returns         => 'F',
                returnsRevenue  => 'J',
                totalRevenue    => 'L',
                mediaType       => 'E',
            },
            option5 => {    # SRD Sales NEW FORMAT
                countryCode     => 'I',
                productType     => 'F',
                clientProductID => 'B',
                artistName      => 'C',
                upc             => 'G',
                albumName       => 'D',
                sales           => 'K',
                salesRevenue    => 'N',
                returns         => 'L',
                returnsRevenue  => 'O',
                totalRevenue    => 'U',
                mediaType       => 'F',
            },
        },
    };
}

sub _unverifiedFieldMapExtended {
    {
        digital => {
            option1 => {
                _itunes_alt_flag => 'M',
            },
            option3 => {
                _currencyFlag => 'I',
            },
            option5 => {
                _deliveryFormat => 'M',
            },
            option6 => {
                _itunes_alt_flag => 'M',
            },
        },
        physical => {
            option1 => {
                _netUnits   => 'M',
                _distFee    => 'O',
                _labelShare => 'R',
            },
            option2 => {
                _netUnits => 'F',
                _distFee  => 'J',
            },
            option3 => {
                _netUnits => 'F',
                _distFee  => 'K',
            },
            option4 => {
                _netUnits => 'F',
                _distFee  => 'K',
            },
            option5 => {
                _netUnits   => 'M',
                _distFee    => 'R',
                _labelShare => 'T',
            },
        },
    }
};

sub _headerIdentifierExtended {
    my $self = shift;

    my $hHeader = {
        digital => {
            option1 => {    # Itunes
                _itunes_alt_flag => 'Label Share',
            },
            option2 => {    # Apple Music
                serviceProductID => 'Apple Identifier',
            },
            option3 => {    # Beats Radio (main)
                _currencyFlag => 'Currency',
            },
            option4 => {    # Beats Radio (alternative)
                price => 'Label Share',
            },
            option5 => {    # SRD Digital | SRD Digital 2 | SRD Digital 3
                price => 'Label Statement',
            },
            option6 => {    # Digital
                _itunes_alt_flag => 'Partner Share Currency',
            },
        },
        physical => {
            option1 => {    # SRD Sales OLD FORMAT
                labelName => 'Sub Label',
            },
            option2 => {    # Morr Music
                productType => 'Format',
            },
            option3 => {    # Labaleine
                productType => 'Format',
            },
            option4 => {    # Bigwax
                productType => 'Format',
            },
            option5 => {    # SRD Sales NEW FORMAT
                countryCode => 'Country of Sale',
            },
        },
    };

    my $sheetName = $self->_sheetName;
    return $hHeader unless $sheetName;
    return {} unless exists $sheetMap{$sheetName};

    # alternative headers for sheets
    if ( $sheetName =~ /^beats radio/i && $self->{_alt_beats_radio_tab} ) {
        $sheetName = 'beats radio alternative';
    }
    if ( $sheetName =~ /^itunes$/i && $self->{_alt_itunes_tab} ) {
        $sheetName = 'itunes alternative';
    }
    if ( $sheetName =~ /^srd sales/i && $self->{_alt_srd_sales_tab} ) {
        $sheetName = 'srd sales alternative';
    }

    my $type   = $sheetMap{$sheetName}[0];
    my $option = $sheetMap{$sheetName}[1];

    my $hRes = {
        $type => {
            $option => $hHeader->{$type}{$option}
        }
    };

    return $hRes;
}

my %sheetRules = (
    # digital
    'itunes' => { # or itunes alternative
        serviceID => Client::Service::DSP_ITUNES,
        productType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('productType') || '';
            my $isrc = $self->_getByFieldName('isrc')        || '';
            return RPS::File::Sale::TYPE_ALBUM if $type =~ /^(?:D|I|M|P|W)$/i;
            return RPS::File::Sale::TYPE_TRACK if $type =~ /^(?:E|F|H|H3|PR|R|S|U|V|X)$/i;
            return $type =~ /^J$/i && $isrc ? RPS::File::Sale::TYPE_TRACK : RPS::File::Sale::TYPE_ALBUM;
        },
        formatType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('formatType') || '';
            return RPS::File::Sale::FORMAT_DOWNLOAD        if $type =~ /^(?:E|M|P|S|V)$/i;
            return RPS::File::Sale::FORMAT_DOWNLOADPREMIUM if $type =~ /^(?:H|H3|I|J)$/i;
            return RPS::File::Sale::FORMAT_TETHERED        if $type =~ /^(?:D|F)$/i;
            return RPS::File::Sale::FORMAT_DOWNLOADUPGRADE if $type =~ /^(?:U|W|X)$/i;
            return RPS::File::Sale::FORMAT_RINGTONE        if $type =~ /^(?:PR|R)$/i;
        },
        mediaType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('mediaType') || '';
            return RPS::DB::Item::MediaType::kMediaTypeAudio if $type =~ /^(?:E|F|H|H3|I|P|PR|R|S|U|W)$/i;
            return RPS::DB::Item::MediaType::kMediaTypeVideo if $type =~ /^(?:D|J|M|V|X)$/i;
        },
        serviceProductID => sub {
            my $self = shift;
            return $self->_getByFieldName('serviceProductID') || '';
        },
        albumName => sub {
            my $self = shift;
            return $self->productType eq RPS::File::Sale::TYPE_ALBUM
                ? $self->_getByFieldName('albumName') || ''
                : '';
        },
        trackName => sub {
            my $self = shift;
            return $self->productType eq RPS::File::Sale::TYPE_TRACK
                ? $self->_getByFieldName('trackName') || ''
                : '';
        },
        currencyCode => 'GBP',
    },
    'apple music' => {
        serviceID => Client::Service::DSP_APPLE_MUSIC,
        productType => RPS::File::Sale::TYPE_TRACK,
        formatType => RPS::File::Sale::FORMAT_STREAM,
        mediaType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('mediaType') || '';
            return RPS::DB::Item::MediaType::kMediaTypeAudio if $type =~ /^1$/i;
        },
        countryCode => sub {
            my $self = shift;
            my $code = $self->_getByFieldName('countryCode') || '';
            return 'GB' if $code =~ /^WW$/i;
        },
        currencyCode => 'GBP',
    },
    'beats radio' => {    # or beats radio (alternative)
        serviceID => Client::Service::DSP_BEATSDIGITAL,
        productType => RPS::File::Sale::TYPE_TRACK,
        formatType => RPS::File::Sale::FORMAT_STREAM,
        mediaType => RPS::DB::Item::MediaType::kMediaTypeAudio,
        currencyCode => 'GBP',
    },
    'srd digital' => {
        productType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('productType') || '';
            return RPS::File::Sale::TYPE_ALBUM if $type =~ /^(?:Album|EP|Single)$/i;
            return RPS::File::Sale::TYPE_TRACK if $type =~ /^Track$/i;
        },
        formatType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('formatType') || '';
            my $deliveryFormat = $self->_getByFieldName('_deliveryFormat') || '';
            return RPS::File::Sale::FORMAT_STREAM   if $type =~ /^(?:Stream|copy_scan)$/;
            return RPS::File::Sale::FORMAT_TETHERED if $type =~ /^(?:Subscription)$/;
            return RPS::File::Sale::FORMAT_DOWNLOAD if !$type || $type =~ /^(?:Download|MP3|WAV|Full)$/i;
            return RPS::File::Sale::FORMAT_DOWNLOAD if ($type =~ /^(?:Error)$/i && $deliveryFormat =~ /^Download$/);
        },
        mediaType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('mediaType') || '';
            return RPS::DB::Item::MediaType::kMediaTypeVideo if $type =~ /copy_scan/i;
            return RPS::DB::Item::MediaType::kMediaTypeAudio;
        },
        albumName => sub {
            my $self = shift;
            return $self->productType eq RPS::File::Sale::TYPE_ALBUM
                ? $self->_getByFieldName('albumName') || ''
                : '';
        },
        trackName => sub {
            my $self = shift;
            return $self->productType eq RPS::File::Sale::TYPE_TRACK
                ? $self->_getByFieldName('trackName') || ''
                : '';
        },
        currencyCode => 'GBP',
    },
    # physical
    'srd sales' => { # OLD FORMAT
        serviceID => Client::Service::DSP_MELODIC,
        _getDateBegin => sub {
            my $self = shift;
            return $self->_getByFieldName('dateBegin');
        },
        currencyCode => 'GBP',
        productType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('productType') || '';
            return RPS::File::Sale::TYPE_CD     if $type =~ /^CD$/i;
            return RPS::File::Sale::TYPE_LP     if $type =~ /^(?:LP|LP2|2L|2L|4L|GP|TS)$/i;
            return RPS::File::Sale::TYPE_LP5    if $type =~ /^(?:7|7B)$/i;
            return RPS::File::Sale::TYPE_EP     if $type =~ /^(?:12|EP|12EP|ML)$/i;
            return RPS::File::Sale::TYPE_DBL_CD if $type =~ /^(?:2D)$/i;
            return RPS::File::Sale::TYPE_DVD    if $type =~ /^(?:DP)$/i;
            return RPS::File::Sale::TYPE_CASS   if $type =~ /^(?:MC)$/i;
        },
        mediaType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('mediaType') || '';
            return RPS::DB::Item::MediaType::kMediaTypeAudio if $type =~ /^(?:CD|LP|LP2|2L|7|12|2D|2L|4L|7B|DP|EP|12EP|GP|ML|TS|MC)$/i;
        },
        sales => sub {
            my $self = shift;
            my $sales = $self->_getByFieldName('sales')               || 0;
            my $totalRevenue = $self->_getByFieldName('totalRevenue') || 0;
            return $totalRevenue >= 0 ? abs $sales : 0;
        },
        salesRevenue => sub {
            my $self = shift;
            my $salesRevenue = $self->_getByFieldName('salesRevenue') || 0;
            my $distFee      = $self->_getByFieldName('_distFee')     || 0;
            my $labelShare   = $self->_getByFieldName('_labelShare')  || 0;
            $salesRevenue = $salesRevenue - $distFee - $labelShare;
            return $salesRevenue >= 0 ? $salesRevenue : 0;
        },
        returns => sub {
            my $self = shift;
            my $returns      = $self->_getByFieldName('returns')      || 0;
            my $totalRevenue = $self->_getByFieldName('totalRevenue') || 0;
            return $totalRevenue < 0 ? abs $returns : 0;
        },
        returnsRevenue => sub {
            my $self = shift;
            my $returnsRevenue = $self->_getByFieldName('returnsRevenue') || 0;
            my $distFee        = $self->_getByFieldName('_distFee')       || 0;
            my $labelShare     = $self->_getByFieldName('_labelShare')    || 0;
            $returnsRevenue = $returnsRevenue - $distFee - $labelShare;
            return $returnsRevenue < 0 ? abs $returnsRevenue : 0;
        },
    },
    'morr music' => {
        serviceID => Client::Service::DSP_MELODIC,
        countryCode => 'DE',
        currencyCode => 'GBP',
        productType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('productType') || '';
            return RPS::File::Sale::TYPE_CD  if $type =~ /^(?:CD|CDEP)$/i;
            return RPS::File::Sale::TYPE_LP  if $type =~ /^(?:LP|2LP|LP \(.+\))$/i;
            return RPS::File::Sale::TYPE_LP5 if $type =~ /^(?:7"|7”)(?: Box)?$/i;
            return RPS::File::Sale::TYPE_EP  if $type =~ /^(?:EP)$/i;
        },
        mediaType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('mediaType') || '';
            return RPS::DB::Item::MediaType::kMediaTypeAudio if $type =~ /^(?:2LP|CD|7"|7" Box|7”|CDEP|EP|LP|LP \(.*?\))$/i;
        },
    },
    'labaleine' => {
        serviceID => Client::Service::DSP_MELODIC,
        countryCode => 'FR',
        currencyCode => 'GBP',
        productType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('productType') || '';
            return RPS::File::Sale::TYPE_CD  if $type =~ /^(?:CD)$/i;
            return RPS::File::Sale::TYPE_LP  if $type =~ /^(?:LP|2LP|LPMP3)$/i;
            return RPS::File::Sale::TYPE_LP5 if $type =~ /^(?:7"|7”|7'')$/i;
        },
        mediaType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('mediaType') || '';
            return RPS::DB::Item::MediaType::kMediaTypeAudio if $type =~ /^(?:CD|LP|2LP|LPMP3|7"|7”|7'')$/i;
        },
    },
    'bigwax' => {
        serviceID => Client::Service::DSP_MELODIC,
        countryCode => 'FR',
        currencyCode => 'GBP',
        productType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('productType') || '';
            return RPS::File::Sale::TYPE_CD  if $type =~ /^(?:CD)$/i;
            return RPS::File::Sale::TYPE_LP  if $type =~ /^(?:LP|2LP|LPMP3)$/i;
            return RPS::File::Sale::TYPE_LP5 if $type =~ /^(?:7"|7''|LP\s?\+\s?7"|LP\s?\+\s?7'')$/i;
        },
        mediaType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('mediaType') || '';
            return RPS::DB::Item::MediaType::kMediaTypeAudio if $type =~ /^(?:CD|LP|2LP|LPMP3|7"|7''|LP\s?\+\s?7"|LP\s?\+\s?7'')$/i;
        },
    },
    'srd sales alternative' => { # NEW FORMAT
        serviceID => Client::Service::DSP_MELODIC,
        _getDateBegin => sub {
            my $self = shift;
            return $self->_getByFieldName('dateBegin');
        },
        currencyCode => 'GBP',
        artistName => sub {
            my $self = shift;
            my $artistName = $self->_getByFieldName('artistName') || '';
            my ($b, $a) = split ',', $artistName;
            $artistName = ($a // '') . ' ' . ($b // '');
            $artistName =~ s/^\s+|\s+$//g;
            $artistName =~ s/\s+/ /g;
            return $artistName;
        },
        productType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('productType') || '';
            return RPS::File::Sale::TYPE_CD     if $type =~ /^CD$/i;
            return RPS::File::Sale::TYPE_LP     if $type =~ /^Vinyl$/i;
        },
        mediaType => sub {
            my $self = shift;
            my $type = $self->_getByFieldName('mediaType') || '';
            return RPS::DB::Item::MediaType::kMediaTypeAudio if $type =~ /^(?:CD|Vinyl)$/i;
        },
        sales => sub {
            my $self = shift;
            return abs $self->_getByFieldName('sales') || 0;
        },
        salesRevenue => sub {
            my $self = shift;
            my $salesRevenue = $self->_getByFieldName('salesRevenue') || 0;
            my $distFee      = $self->_getByFieldName('_distFee')     || 0;
            my $labelShare   = $self->_getByFieldName('_labelShare')  || 0;
            return $salesRevenue > 0
                ? abs($salesRevenue + $distFee - $labelShare)
                : $salesRevenue;
        },
        returns => sub {
            my $self = shift;
            return abs $self->_getByFieldName('returns') || 0;
        },
        returnsRevenue => sub {
            my $self = shift;
            my $returnsRevenue = $self->_getByFieldName('returnsRevenue') || 0;
            my $distFee        = $self->_getByFieldName('_distFee')       || 0;
            my $labelShare     = $self->_getByFieldName('_labelShare')    || 0;
            return $self->salesRevenue > 0
                ? abs $returnsRevenue
                : abs($returnsRevenue + $distFee - $labelShare);
        },
    },
);

sub _sheetName {
    my $self = shift;

    my $name = $self->sheetname() || '';
    $name =~ s/^\s+|\s+$//g;
    $name =~ s/[^0-9a-zA-Z\s]//g;
    $name =~ s/\s+/ /g;
    $name =~ s/(.*)/\L$1/;

    # sheets aliases
    if ( $name =~ /^SRD Digital/i ) {
        $name = 'srd digital';
    }

    return $name;
}

sub _sheetRule {
    my $self = shift;

    my $sheet    = $self->_sheetName();
    if ( $sheet =~ /^srd sales$/i && $self->{_alt_srd_sales_tab} ) {
        $sheet = 'srd sales alternative';
    }

    my ($method) = (caller(1))[3] =~ /.*::(.+)$/;
    return unless exists $sheetRules{$sheet} && exists $sheetRules{$sheet}{$method};

    my $rule = $sheetRules{$sheet}{$method};
    return ref $rule eq 'CODE' ? &$rule($self, @_) : $rule;
}

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

    # get dateBegin from col. C15 of the 'Statement$' sheet
    if ( $self->_sheetName =~ /^Statement$/i ) {
        foreach my $aLine ( @$sheet[0..15] ) {
            next unless ref $aLine eq 'ARRAY';
            my $date = $aLine->[2] || '';
            $date =~ s/[^\w\s]//g;
            if ( $date =~ /^(\w+) (\d{4}).*$/ ) {
                $self->{_dateBegin} = "$1 $2" unless $self->{_dateBegin};
            }
        }
    }

    # determine an alternative header format for the 'beats radio' sheet
    if ( $self->_sheetName =~ /^beats radio$/i ) {
        $self->{_alt_beats_radio_tab} = 0;
        foreach my $aLine ( @$sheet[0..15] ) {
            # col. I is 'Currency'
            if ( $aLine->[2] =~ /^ISRC$/i && $aLine->[8] !~ /^Currency$/i ) {
                next if $self->{_alt_beats_radio_tab};
                $self->{_alt_beats_radio_tab} = 1 ;
            }
        }
    }
    # determine an alternative header format for the 'itunes' sheet
    if ( $self->_sheetName =~ /^itunes$/i ) {
        $self->{_alt_itunes_tab} = 0;
        # col. M is 'Partner Share Currency'
        if ( $sheet->[0]->[5] =~ /^Quantity$/i && $sheet->[0]->[12] =~ /^Partner Share Currency$/i ) {
            next if $self->{_alt_itunes_tab};
            $self->{_alt_itunes_tab} = 1 ;
        }
    }
    # determine an alternative header format for the 'srd sales' sheet
    if ( $self->_sheetName =~ /^srd sales/i ) {
        $self->{_alt_srd_sales_tab} = 0;
        foreach my $aLine ( @$sheet[0..15] ) {
            # col. A is 'Label'
            if ( $aLine->[0] =~ /^Label$/i && $aLine->[1] =~ /^Catalog No$/i ) {
                next if $self->{_alt_srd_sales_tab};
                $self->{_alt_srd_sales_tab} = 1;
            }
        }
    }

    # skip sheets
    if ( $self->_sheetName =~ /^(?:SRD Shortfall)/i ) {
        return;
    }

    my $supportedSheet = grep { $self->_sheetName =~ /^$_/ } keys %sheetMap;
    unless ( $self->_sheetName =~ /^Statement|Banked Income|Expenditure|Overstocks|IHP Breakdowns|Shipping Breakdown|Morr Charges$/i || $supportedSheet  ) {
        $self->fail("Unsupported sheet: '" . $self->sheetname . "'");
    }

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

sub _isValidSaleRecord {
    my $self = shift;

    my $type = $self->_getByFieldName('productType') || '';
    return if $type =~ /^Amazon Vinyl Handling Fee$/i;

    return ( $self->_getByFieldName('trackName') || $self->_getByFieldName('albumName') || $self->_getByFieldName('artistName') )
       && ( $self->price || $self->units || $self->_getByFieldName('sales') || $self->_getByFieldName('returns') || $self->_getByFieldName('totalRevenue') );

}

# methods

sub priceLevel    { RPS::File::Sale::PLEVEL_UNKNOWN }
sub channel       { RPS::File::Sale::CHANNEL_RETAIL }

sub _getDateBegin {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

    return $self->{_dateBegin};
}

sub labelName {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

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

sub serviceID {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

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

    return $self->_sheetName =~ /^srd digital$/i
        ? $self->handleError( "Unknown service: '$service'", RPS::DB::Item::SaleImportError::kErrorService )
        : $self->fail("Unable to determine service from: '$service' ");
}

sub countryCode {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

    my $name = $self->_getByFieldName('countryCode') || '';
    $name =~ s/^\s*|\s*$//g;

    if ( $name ) {
        my $oCountry = Common::Country->Get($name);
        return $oCountry->alpha2() if $oCountry;
    }

    $self->fail( "Unable to determine country from: '$name' " );
}

sub productType {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

    my $type = $self->_getByFieldName('productType') || '';
    $self->fail( "Unable to determine productType from: '$type' " );
}

sub formatType {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

    my $type = $self->_getByFieldName('formatType') || '';
    $self->fail( "Unable to determine formatType from: '$type' " );
}

sub mediaType {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

    my $type = $self->_getByFieldName('mediaType') || '';
    $self->fail( "Unable to determine mediaType from: '$type' " );
}

sub serviceProductID {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

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

sub upc {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

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

sub isrc {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

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

sub currencyCode {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if $result;

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

sub artistName {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if defined $result;

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

sub albumName {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if defined $result;

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

sub trackName {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if defined $result;

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

# digital
sub price     { abs( shift->_getByFieldName('price') || 0 ) }
sub unitPrice { abs( shift->SUPER::unitPrice) }
sub units {
    my $self = shift;

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

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

    return $units;
}

# physical
sub sales {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if defined $result;

    my $sales        = $self->_getByFieldName('sales')        || 0;
    my $salesRevenue = $self->_getByFieldName('salesRevenue') || 0;
    return $sales >= 0 && $salesRevenue > 0 ? $sales : 0;
}

sub salesRevenue {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if defined $result;

    my $salesRevenue = $self->_getByFieldName('salesRevenue') || 0;
    my $distFee      = $self->_getByFieldName('_distFee')     || 0;
    $salesRevenue -= $distFee;
    return $salesRevenue >= 0 ? $salesRevenue : 0;
}

sub returns {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if defined $result;

    my $netUnits       = $self->_getByFieldName('_netUnits')      || 0;
    my $returnsRevenue = $self->_getByFieldName('returnsRevenue') || 0;
    my $distFee        = $self->_getByFieldName('_distFee')       || 0;
    $returnsRevenue -= $distFee;
    return $returnsRevenue < 0 ? abs($netUnits) : 0;
}

sub returnsRevenue {
    my $self = shift;

    my $result = $self->_sheetRule();
    return $result if defined $result;

    my $returnsRevenue = $self->_getByFieldName('returnsRevenue') || 0;
    return $returnsRevenue < 0 ? abs($returnsRevenue) : 0;
}

# mapFace
sub _mapFaceServiceID   { 'serviceID' }
sub _mapFaceCountryCode {}
sub _mapFaceProductType {}
sub _mapFaceFormatType  {}
sub _mapFaceMediaType   {}


1;
