package BookPub::RDAS::Request::SaleFeedFileList::BarnesNoble;

use WWW::Mechanize;
use Data::Dumper;

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

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

use lib '/app/tools/bookpub/lib';
use BookPub::ServiceCredential;
use BookPub::Sale::Feed::SaleFeedService;
use BookPub::RDAS::Parser::SaleData::BarnesNoble::Home;
use BookPub::RDAS::Parser::SaleData::BarnesNoble::FileList;

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

use constant kBaseURL => 'https://finance.bnsupplier.com';

sub reportFrequency { 'daily' }

sub serviceID { return BookPub::Tracker::Service::BARNES_NOBLE() }

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

sub _init {
    my $self = shift->SUPER::_init(@_);

    # Disable host name verification because B&N certificate isn't
    $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

    assert( $self->saleFeedServiceID );

    $self->{_service} = new BookPub::Sale::Feed::SaleFeedService( saleFeedServiceID => $self->saleFeedServiceID );
    $self->{_feed} = new BookPub::Sale::Feed::SaleFeed( saleFeedID => $self->saleFeedID ) if ( $self->saleFeedID );

    die "Unable to find service credentials." unless ( $self->service );

    return $self;
}

sub _getFetchObject {
    my $self = shift;
    my $url  = shift || die;
    my $ua   = $self->userAgent;

    return RDAS::Fetcher::Mechanize::Authenticated->new(
        maxRedirect => 6,
        url         => $url,
        userAgent   => $ua,
        scripter    => 1,
    );
}

sub service { shift->{_service} }
sub parsers { shift->{_parsers} }
sub files   { shift->{_files} }
sub feed    { shift->{_feed} }

sub Files {
    my $self = shift;

    unless ( $self->files ) {
        $self->fetch();
    }

    return $self->files;
}

sub Feeds {
    my $self = shift;

    my $files = $self->Files();

    my %feeds;

    foreach my $file (@$files) {
        Log->info("$file->{filename}");
        if ( $file->{filename} =~ /(ebook_int_)\d+_(\d+_\d+.*)\./i ) {
            $feeds{"$1$2"} = 1;
        } elsif ( $file->{filename} =~ /\d+_(\d+_\d+.*)\./ ) {
            $feeds{$1} = 1;
        }
    }

    my @feeds;

    foreach my $feed ( keys %feeds ) {
        if ( $feed =~ /ebook_int_/i ) {
            push( @feeds, { name => $feed, feed => $feed } );
        } else {
            push( @feeds, { name => "eBook_Pay_$feed", feed => $feed } );
        }
    }

    return \@feeds;
}

sub fetch {
    my $self = shift;
    $self->{_error} = undef;

    return $self->_fetchFileList() if ( $self->_login() );
}

sub _credentials {
    my $self = shift;

    unless ( $self->{_credentials} ) {
        my $cred = new BookPub::Sale::Feed::SaleFeedService( saleFeedServiceID => $self->service->SaleFeedServiceID );
        if ( $cred && $cred->Username && $cred->Password ) {
            $self->{_credentials} = [ $cred->Username, $cred->Password ];
        }
    }

    if ( $self->{_credentials} ) {
        return @{ $self->{_credentials} };
    } else {
        die "No login credentials";
    }
}

sub _login {
    my $self = shift;
    my ( $uname, $passwd ) = $self->_credentials();
    my $url  = kBaseURL . "/OA_HTML/AppsLogin";
    my %args = (
        usernameField => $uname,
        passwordField => $passwd,
    );
    my $fetcher = $self->_fetchPage( $url, form => \%args, click => 'Login' ) || return;

    my $parser = new BookPub::RDAS::Parser::SaleData::BarnesNoble::Home( content => $fetcher->content() );
    if ( $parser->Logout ) {
        Log->info(" ++ Login successful ++");
    } else {
        Log->error("Authentication failed");
        return;
    }

    $self->{_parsers}->{home} = $parser;

    return 1;
}

sub _fetchFileList {
    my $self = shift;
    my $saleFeedID = $self->feed->SaleFeedID if ( $self->feed );
    my $startDate;

    if ( $self->feed ) {
        $startDate = new Common::Date( $self->feed->DownloadStartDate() );
    } else {
        $startDate = new Common::Date( $self->service->DownloadStartDate() );
    }

    assert($startDate);

    my $url = kBaseURL . $self->parsers->{home}->InvoiceLink();

    Log->info(" + Fetch search page");

    my $form = {
        SearchInvoiceNum      => 'e_ook',
        SearchInvoiceDateFrom => $startDate->asString("%m/%d/%Y"),
    };

    my $fetcher = $self->_fetchPage( $url, form => $form, click => 'Go' ) || return;

    my $parser = new BookPub::RDAS::Parser::SaleData::BarnesNoble::FileList( content => $fetcher->content() );
    if ( $parser->Error() ) {
        Log->error( "Fetch failed: " . $parser->Error() );
        return;
    }

    $self->_processFileList( $parser->Files() );

    while ( $parser->NextLink() ) {
        $fetcher->click('Next 25') || return;

        my $parser = new BookPub::RDAS::Parser::SaleData::BarnesNoble::FileList( content => $fetcher->content() );
        if ( $parser->Error() ) {
            Log->error( "Fetch next page failed: " . $parser->Error() );
            return;
        }

        $self->_processFileList( $parser->Files() );
    }

    return $self->files;
}

sub _processFileList {
    my $self  = shift;
    my $files = shift;

    if ($files) {
        $self->{_files} = [] unless ( $self->files );

        my $feedName = $self->feed->Name() if ( $self->feed );
        my $feedLeft;
        my $feedRight;
        my $feedPattern;

        if ($feedName) {
            ($feedLeft) = $feedName =~ /^(ebook_int)/i;
            $feedLeft = 'eBook_Pay' if !$feedLeft;
            ($feedRight) = $feedName =~ /^.*?(\d+_\d+.*)$/;
            $feedPattern = $feedLeft . '_\d+_' . $feedRight . '.csv';
        }

        foreach my $file (@$files) {

            # Limit results to a specific feed if we specified a feed.
            if ( !$feedName || $file->{filename} =~ /^$feedPattern$/i ) {
                push( @{ $self->{_files} }, $file );
            }
        }
    }
}

1;
