package BookPub::RDAS::Request::SalesData::BarnesNoble;

use WWW::Mechanize;
use Data::Dumper;
use Fcntl qw(:DEFAULT :flock);

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

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::Report;
use BookPub::RDAS::Response::SalesData::BarnesNoble;

use BookPub::Sale::Feed::SaleFeedFile;
use BookPub::Sale::Feed::SaleFeed;

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

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

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

sub _getResponseObject {
    my $self = shift;

    return new BookPub::RDAS::Response::SalesData::BarnesNoble( report => $self->report, saleFeedFileID => $self->saleFeedFileID, @_ );
}

sub _init {

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

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

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 fetch {
    my $self = shift;
    $self->{_error} = undef;

    my $url = $self->_fetchFile() if ( $self->_login() );

    return $self->_getContent($url);
}

sub parsers { shift->{_parsers} }

sub _credentials {
    my $self = shift;

    my $saleFeedFile = new BookPub::Sale::Feed::SaleFeedFile( saleFeedFileID => $self->saleFeedFileID );
    my $saleFeed = new BookPub::Sale::Feed::SaleFeed( saleFeedID => $saleFeedFile->SaleFeedID );

    unless ( $self->{_credentials} ) {
        my $cred = new BookPub::Sale::Feed::SaleFeedService( saleFeedServiceID => $saleFeed->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 _fetchFile {
    my $self      = shift;
    my $startDate = new Common::Date( $self->SaleFeedFile->StartDate );
    my $endDate   = new Common::Date( $self->SaleFeedFile->EndDate )->addDays(4);
    my $url       = kBaseURL . $self->parsers->{home}->InvoiceLink();
    my $submit    = 'Icxgocontrol';
    my ($filename) = split( /\./, $self->SaleFeedFile->Filename );

    Log->info( " + Fetch file page: " . $self->SaleFeedFile->Filename );

    my $form = { SearchInvoiceNum => "$filename", };

    Log->info( "POST DATA: " . Dumper $form );
    my $fetcher = $self->_fetchPage( $url, form => $form, click => 'Go' ) || return;

    Log->info("Parsing content.");
    my $parser = new BookPub::RDAS::Parser::SaleData::BarnesNoble::FileList( content => $fetcher->content() );

    if ( $parser->Error() ) {
        Log->error( "Fetch failed: " . $parser->Error() );
        return;
    }

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

    if ($files) {
        Log->debug($files);
        print $parser->content() unless (@$files);
        foreach my $file (@$files) {
            if ( $self->SaleFeedFile->Filename eq $file->{filename} ) {
                Log->info( "MATCH: " . $self->SaleFeedFile->Filename . " eq $file->{filename}" );
                return $file->{link};
            }
        }
    }

    return;
}

sub _getContent {
    my $self = shift;
    my $url = shift || die "URL Required";

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

    my $fetcher = $self->_fetchPage( kBaseURL . '/OA_HTML/' . $url, form => {}, click => 'Export', download => 'export.csv' ) || return;

    if ( $fetcher->filename() =~ /.csv$/ ) {
        return $self->{_report} = $fetcher->content();
    }

    # If the sale file end date is > 30 days old then mark the file as invalid so
    # we don't try to download (or notify) again.
    my $notificationDate = new Common::Date->now()->addDays(-30);
    my $endDate          = new Common::Date( $self->SaleFeedFile->EndDate() );

    if ( $notificationDate > $endDate ) {
        $self->SaleFeedFile->Status('invalid');
        $self->SaleFeedFile->save();
    }

    die "Sale report missing from service";
}

1;
