package BookPub::RDAS::Request::POSData;

use Data::Dumper;

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

use lib '/app/tools/bookpub/lib';
use BookPub::POS::Sale::Feed;
use BookPub::DB::Item::POSFile;
use BookPub::POS::Tracker::File;

use base 'BookPub::RDAS::Request';

sub _validOptions {
    return ( reportDate, shift->SUPER::_validOptions() );
}

sub _init {
    my $self = shift;
    my %args = @_;

    $self->{_feed} = new BookPub::POS::Sale::Feed( serviceID => $self->_getResponseObject()->serviceID );
    $self->{_retry} = $args{retry};

    return $self->SUPER::_init(@_);
}

sub feed  { shift->{_feed} }
sub files { shift->{_files} }
sub retry { shift->{_retry} }

# How many days do we look back for missing files?
sub monitorDays { 14 }

sub run {
    my $self = shift;

    if ( $self->fetch(@_) ) {
        $self->respond();
    }
}

sub GetRequestObject {
    my $class     = shift;
    my $serviceID = shift;
    my %args      = @_;

    assert( $serviceID, "Service ID Required" );

    my %classes = (
        BookPub::Tracker::Service::APPLE()        => BookPub::RDAS::Request::POSData::Apple,
        BookPub::Tracker::Service::AMAZON()       => BookPub::RDAS::Request::POSData::Amazon,
        BookPub::Tracker::Service::BARNES_NOBLE() => BookPub::RDAS::Request::POSData::BarnesNoble,
    );

    my $type = $classes{"$serviceID"};

    die "Not a valid RDAS service id: $serviceID\n" unless ($type);

    eval "use $type";
    die "$@" if ($@);

    return $type->new(%args);
}

# Create pos_file records for all the files we expect.
sub _initPOSFiles {
    my $self = shift;
    my %files;
    my @monitorDays;

    if ( $self->retry() ) {
        my $dbItem = BookPub::DB::Item::POSFile->Lookup( pos_file_id => $self->retry );
        die "ERROR: POS File ID " . $self->retry . " not found" unless ($dbItem);

        my $file = BookPub::POS::Tracker::File->new( dbItem => $dbItem );

        $file->setRetry();

        $files{ $file->DateStart } = $file->POSFileID();

        $self->{_reportDate} = $file->DateStart();

        die("No date set in pos_file record") unless ( $file->DateStart() );
    }

    if ( $self->reportDate() ) {

        # Do nothing.  We don't need stage a file record when a specific report date is requested
    } else {
        @monitorDays = $self->_getMonitorDays();
    }

    foreach my $date ( sort @monitorDays ) {
        my $form = $self->_getFileFormObject( startDate => $date );

        my $dbItem = BookPub::DB::Item::POSFile->Create();
        $dbItem->save();

        my $file = BookPub::POS::Tracker::File->new( dbItem => $dbItem );
        $file->DateStart( $form->StartDate );
        $file->DateEnd( $form->EndDate );

        $file->setStatusFetching();

        $files{$date} = $file->POSFileID();
    }

    $self->{_files} = \%files;
}

sub _getMonitorDays {
    my $self = shift;
    my @days;
    my $today     = Common::Date->now();
    my $yesterday = $today->clone->addDays(-1);
    my $startDate = $yesterday->clone->addDays( -1 * ( $self->monitorDays - 1 ) );

    for ( my $date = $startDate ; $startDate <= $yesterday ; $startDate->addDays(1) ) {
        unless ( $self->feed->isPassedStartDate($date) ) {
            next;
        }

        unless ( $self->feed->isNew($date) ) {
            next;
        }

        push( @days, $date->asString() );
    }

    return @days;
}

# If the request processes fails during a fetch we need to mark all files as
# failed.
sub _POSFileFail {
    my $self = shift;

    foreach my $id ( keys %{ $self->files } ) {
        my $file = BookPub::POS::Tracker::File->new( posFileID => $id );
        $file->Notes("Fetch process failed");
        $file->setStatusFetchError();
    }
}

# Check to see if all files we expected to download actually downloaded.  If they
# didn't change the status to error.
sub _POSFileMissing {
    my $self = shift;

    foreach my $id ( keys %{ $self->files } ) {
        my $file = BookPub::POS::Tracker::File->new( posFileID => $id ) if ($id);
        if ( $file && $file->POSFileID && $file->POSFileID == BookPub::DB::Item::POSFile::STATUS_FETCHING ) {
            $file->Notes("Missing file from vendor");
            $file->setStatusFetchError();
        }
    }
}

1;
