#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2011 RoyaltyShare, Inc.   All Rights Reserved
#---------------------------------------------------------------
package BookPub::RDAS::Process::FetchSales;

use Data::Dumper;

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

use lib '/app/tools/bookpub/lib';
use BookPub::DB::Item::SaleFeed;
use BookPub::DB::Item::SaleFeedService;
use BookPub::RDAS::Request::SaleFeedAuthCheck;
use BookPub::Sale::Feed::SaleFeedFileList;
use BookPub::Sale::Feed::SaleFeedServiceList;
use BookPub::Sale::Feed::SaleFeedFileList::Missing;
use BookPub::Sale::Feed::SaleFeedList;
use BookPub::Sale::Feed::SaleFeed::WithFiles;

use lib '/app/tools/rdas/lib';
use RDAS::Fetcher::Mechanize::Authenticated;

use base 'BookPub::RDAS::Process';

sub _options {
    my $self    = shift;
    my $options = $self->SUPER::_options(@_);
    $options->{client_id} = {
        short       => 'c',
        description => 'Limit to this client id',
        parameter   => 'i'
    };

    $options->{date} = {
        short       => 't',
        description => 'Download for this date',
        parameter   => 'i'
    };

    $options->{sales_feed_id} = {
        short       => 'i',
        description => 'Only download for this feed id',
        parameter   => 'i'
    };

    $options->{auth_check} = {
        short       => 'a',
        description => 'Auth check only',
    };

    $options->{report_missing} = {
        short       => 'm',
        description => 'Only report missing files',
    };

    $options->{available_files} = {
        short       => 'z',
        description => 'List all available sales files',
    };

    $options->{available_feeds} = {
        short       => 'f',
        description => 'List all available sales feeds',
    };

    $options->{preserve_login} = {
        short       => 'k',
        description => 'Login in once per sale feed',
    };

    return $options;
}

sub _jobClass { 'BookPub::RDAS::Job::RunFetchSales' }

sub _process {
    my $self = shift;

    Log->notice( "** Processing Client ID: " . Common::RSApp::GetClientID() );

    my $feedID = $self->param('sales_feed_id') || return $self->SUPER::_process(@_);

    my $services = new BookPub::Sale::Feed::SaleFeedServiceList();

    return $self->_reportMissingFiles( saleFeedID => $self->param('sales_feed_id') )
      if ( $self->param('report_missing') );

    $self->_processFeeds( salesFeedID => $self->param('sales_feed_id') );
}

sub _processService {
    my $self = shift;
    my $serviceID = shift || die;

    Log->notice("** Begin service process, Service ID: $serviceID");
    my $list = new BookPub::Sale::Feed::SaleFeedServiceList( serviceID => $serviceID );

    foreach my $saleFeedService ( @{ $list->{SaleFeedService} } ) {
        $self->_processServiceFeed( $saleFeedService->SaleFeedServiceID() );
    }

}

sub _processServiceFeed {
    my $self = shift;
    my $saleFeedServiceID = shift || die;

    Log->notice("** Begin feed service process, Sale Feed Service: $saleFeedServiceID");

    # Clears out Fetching all available files
    RDAS::Fetcher::Mechanize::Authenticated::ClearSingleton();

    if ( $self->param('auth_check') ) {
        $self->_authCheck($saleFeedServiceID);
    } elsif ( $self->param('available_files') ) {
        $self->_listAvailableFiles($saleFeedServiceID);
    } elsif ( $self->param('available_feeds') ) {
        $self->_listAvailableFeeds($saleFeedServiceID);
    } elsif ( $self->param('report_missing') ) {
        $self->_reportMissingFiles( saleFeedServiceID => $saleFeedServiceID );
    } else {
        $self->_processFeeds( saleFeedServiceID => $saleFeedServiceID );
    }
}

sub _authCheck {
    my $self              = shift;
    my $saleFeedServiceID = shift;

    my $service = new BookPub::Sale::Feed::SaleFeedService( saleFeedServiceID => $saleFeedServiceID );

    Log->info("Running auth check only for sale feed service: $saleFeedServiceID");
    my $auth = BookPub::RDAS::Request::SaleFeedAuthCheck->GetRequestObject( $service->ServiceID, saleFeedServiceID => $saleFeedServiceID );

    print $auth->run ? "Authentication Successful\n" : "Authenication Failed!\n";
}

sub _listAvailableFiles {
    my $self              = shift;
    my $saleFeedServiceID = shift;

    assert($saleFeedServiceID);

    Log->notice("-- Listing available files for sale feed service: $saleFeedServiceID");

    my $list = new BookPub::Sale::Feed::SaleFeedFileList( saleFeedServiceID => $saleFeedServiceID );
    $list->fetch();

    foreach my $file ( @{ $list->{SaleFeedFile} } ) {
        print $file->{Filename} . " (status: " . $file->{Status} . ")\n";
        Log->debug( Dumper $file );
    }
}

sub _listAvailableFeeds {
    my $self              = shift;
    my $saleFeedServiceID = shift;

    Log->info("Listing available feeds for sale feed service: $saleFeedServiceID");
    my $list = new BookPub::Sale::Feed::SaleFeedList( saleFeedServiceID => $saleFeedServiceID );
    $list->fetch();

    foreach my $file ( @{ $list->{SaleFeed} } ) {
        print $file->{Name} . " (status: " . $file->{Status} . ")\n";
    }
}

sub _processFeeds {
    my $self              = shift;
    my %args              = @_;
    my $saleFeedServiceID = $args{saleFeedServiceID};
    my $feedID            = $args{salesFeedID};

    die "Sale Feed Service ID or Sale Feed ID Required.\n" unless ( $saleFeedServiceID || $feedID );

    my $saleFeedService;

    # Storing the sale feed service id in a separate variable so that we
    # don't get confused about what was actually passed in.
    my $sfsID;

    # Let's stop right here if the sale feed service is not verified.
    if ($saleFeedServiceID) {
        $saleFeedService = BookPub::DB::Item::SaleFeedService->Lookup( sale_feed_service_id => $saleFeedServiceID );
        $sfsID = $saleFeedServiceID;
    } else {
        my $saleFeed = BookPub::DB::Item::SaleFeed->Lookup( sale_feed_id => $feedID );
        $sfsID = $saleFeed->sale_feed_service_id();
        $saleFeedService = BookPub::DB::Item::SaleFeedService->Lookup( sale_feed_service_id => $sfsID );
    }

    if ( $saleFeedService->verified == 1 ) {
        if ($saleFeedServiceID) {
            Log->info("Processing feeds for sale feed service: $saleFeedServiceID");

            Log->info(" -- Fetching available feeds for service: $saleFeedServiceID");
            my $list = new BookPub::Sale::Feed::SaleFeedList( saleFeedServiceID => $saleFeedServiceID );
            $list->fetch();

            if ( !$self->param('preserve_login') || RDAS::Fetcher::Mechanize::Authenticated::LoggedIn() ) {
                foreach my $feed ( @{ $list->{SaleFeed} } ) {
                    if ( $feed->Status eq 'active' ) {
                        $self->_processFeed( $feed->SaleFeedID );
                    } else {
                        Log->notice( " -- Ignoring feed ID: " . $feed->SaleFeedID . " status: " . $feed->Status() );
                    }
                }
            }
        } else {
            Log->info("Processing feed id: $feedID");
            $self->_processFeed($feedID);
        }
    } else {
        Log->notice( "Sale feed service: $sfsID is not verified. Client ID: " . Common::RSApp::GetClientID );
    }
}

sub _processFeed {
    my $self   = shift;
    my $feedID = shift;

    Log->notice(" ** Begin feed download, feed id: $feedID");

    RDAS::Fetcher::Mechanize::Authenticated::ClearSingleton() if !$self->param('preserve_login');

    my $feed = new BookPub::Sale::Feed::SaleFeed::WithFiles( saleFeedID => $feedID );

    die "Unknown feed id: $feedID\n" unless ( $feed->SaleFeedID );
    die "feed id: $feedID is not active\n" unless ( $feed->Status eq 'active' );

    foreach my $file ( @{ $feed->Files->{SaleFeedFile} } ) {
        RDAS::Fetcher::Mechanize::Authenticated::ClearSingleton() if !$self->param('preserve_login');
        $file->download();
    }

    # Search for / Store missing files.
    my $list = new BookPub::Sale::Feed::SaleFeedFileList::Missing( saleFeedID => $feedID );

}

sub _getServiceIDs {
    my $self = shift;
    my @result;

    my @serviceIDs = $self->SUPER::_getServiceIDs(@_);

    foreach my $serviceID (@serviceIDs) {
        if ( BookPub::DB::Item::SaleFeedService->Lookup( service_id => $serviceID ) ) {
            push( @result, $serviceID );
        }
    }

    Log->notice( "No services configured in sale_feed_service table. Client ID: " . Common::RSApp::GetClientID ) unless ( @result > 0 );

    return @result;
}

sub _reportMissingFiles {
    my $self              = shift;
    my %args              = @_;
    my $saleFeedServiceID = $args{saleFeedServiceID};
    my $saleFeedID        = $args{saleFeedID};

    assert( $saleFeedServiceID || $saleFeedID );

    my $list = new BookPub::Sale::Feed::SaleFeedFileList::Missing( saleFeedID => $saleFeedID, saleFeedServiceID => $saleFeedServiceID );

    foreach my $file ( @{ $list->{SaleFeedFile} } ) {

        #print $file->{Filename} . " (status: " . $file->{Status} . ")\n";
    }

}

sub _getProductionClientIDs {
    return Common::RSDB::GetAllBookPubClientIDs();
}

1;
