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

use strict;
use warnings;

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

use lib '/app/tools/bookpub/lib';
use BookPub::Catalog::ProductServiceUrl;
use BookPub::Catalog::Product::Book;
use BookPub::Catalog::ProductFormat;
use BookPub::Catalog::Book::WithAuthor;
use BookPub::RDAS::Form::ProductMonitor::ProductMonitorItem::Availability;
use BookPub::RDAS::Form::ProductMonitor::ProductMonitorItem::CoverArt;
use BookPub::RDAS::Form::ProductMonitor::ProductMonitorItem::Failure;
use BookPub::RDAS::Form::ProductMonitor::ProductMonitorItem::Metadata;
use BookPub::RDAS::Form::ProductMonitor::ProductMonitorItem::Price;
use BookPub::RDAS::Form::ProductMonitor::ProductMonitorItem::Rank;

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

sub _options {
    {
        client_id => {
            short       => 'c',
            required    => 1,
            description => 'Limit to this client id',
            parameter   => 'i'
        },
        service_id => {
            short       => 's',
            required    => 1,
            description => 'Limit to this service id',
            parameter   => 'i'
        },
        count => {
            short       => 'n',
            description => 'Only fetch/generate n urls',
            parameter   => 'i'
        },
        service_list => {
            short       => 'y',
            description => 'List all monitored services',
        },
        current => {
            description => 'Only report products that have fetched information',
        },
    };
}

sub _processService {
    my $self                 = shift;
    my $serviceID            = shift || die;
    my $totalProduct         = 0;
    my $totalFailures        = 0;
    my $authorValidationFail = 0;
    my $titleValidationFail  = 0;
    my $urlFail              = 0;
    my $detailFieldFail      = 0;
    my $authorFieldFail      = 0;
    my $formatFieldFail      = 0;
    my $publisherFieldFail   = 0;
    my $priceFieldFail       = 0;
    my $fetchFail            = 0;
    my $noIsbnMatchFail      = 0;

    Log->debug("** Begin service process, Service ID: $serviceID");

    foreach my $product ( $self->_productList($serviceID) ) {
        $totalProduct++;
        Log->info( " - Fetching info for product " . $product->ProductID );

        my $retval = $self->_processProduct( $serviceID, $product->ProductID );

        if ($retval) {
            if ( $retval =~ "Author validation failed" ) {
                $authorValidationFail++;
                $totalFailures++;
            }
            if ( $retval =~ "Title validation failed" ) {
                $titleValidationFail++;
                $totalFailures++;
            }
            if ( $retval =~ "Unable to determine product page url" ) {
                $urlFail++;
                $totalFailures++;
            }
            if ( $retval =~ "missing: ProductDetail, Title, Author" ) {
                $detailFieldFail++;
                $totalFailures++;
            }
            if ( $retval =~ "missing: Author" ) {
                $authorFieldFail++;
                $totalFailures++;
            }
            if ( $retval =~ "missing: Format, ProductPrice" ) {
                $formatFieldFail++;
                $totalFailures++;
            }
            if ( $retval =~ "missing: Publisher, ISBN13, Author, Title, ProductPrice" ) {
                $publisherFieldFail++;
                $totalFailures++;
            }
            if ( $retval =~ "missing: ProductPrice" ) {
                $priceFieldFail++;
                $totalFailures++;
            }
            if ( $retval =~ "Fetch failed.  HTTP Code: 500" ) {
                $fetchFail++;
                $totalFailures++;
            }
            if ( $retval =~ "No match found for ISBN:" ) {
                $noIsbnMatchFail++;
                $totalFailures++;
            }
        }
    }

    my $percent;
    my $name = $self->_getServiceName($serviceID);

    print "Service Name: $name\n";
    $percent = ( $totalFailures / $totalProduct ) * 100;
    printf "Total Failures: %.2f%% (%d/%d)\n", $percent, $totalFailures, $totalProduct;

    $percent = ( $authorValidationFail / $totalProduct ) * 100;
    printf "Author Validation Failures: %.2f%% (%d/%d)\n", $percent, $authorValidationFail, $totalProduct;

    $percent = ( $titleValidationFail / $totalProduct ) * 100;
    printf "Title Validation Failures: %.2f%% (%d/%d)\n", $percent, $titleValidationFail, $totalProduct;

    $percent = ( $urlFail / $totalProduct ) * 100;
    printf "URL Failures: %.2f%% (%d/%d)\n", $percent, $urlFail, $totalProduct;

    $percent = ( $detailFieldFail / $totalProduct ) * 100;
    printf "Missing ProductDetail/Title/Author Field Failures: %.2f%% (%d/%d)\n", $percent, $detailFieldFail, $totalProduct;

    $percent = ( $authorFieldFail / $totalProduct ) * 100;
    printf "Missing Author Field Failures: %.2f%% (%d/%d)\n", $percent, $authorFieldFail, $totalProduct;

    $percent = ( $formatFieldFail / $totalProduct ) * 100;
    printf "Missing Format/ProductPrice Field Failures: %.2f%% (%d/%d)\n", $percent, $formatFieldFail, $totalProduct;

    $percent = ( $publisherFieldFail / $totalProduct ) * 100;
    printf "Missing Publisher/ISBN13/Author/Title/ProductPrice Field Failures: %.2f%% (%d/%d)\n",
      $percent, $publisherFieldFail, $totalProduct;

    $percent = ( $priceFieldFail / $totalProduct ) * 100;
    printf "Missing Price Field Failures: %.2f%% (%d/%d)\n", $percent, $priceFieldFail, $totalProduct;

    $percent = ( $noIsbnMatchFail / $totalProduct ) * 100;
    printf "No Match Found For ISBN Failures: %.2f%% (%d/%d)\n", $percent, $noIsbnMatchFail, $totalProduct;
}

sub _processProduct {
    my $self      = shift;
    my $serviceID = shift;
    my $productID = shift;

    assert($serviceID);
    assert($productID);

    return $self->_checkFailure( $productID, $serviceID );

}

sub _productList {
    my $self      = shift;
    my $serviceID = shift;
    my $current   = $self->param('current');
    my $limit     = $self->param('count');

    my $ebookOnly;
    unless ($ebookOnly) {
        my $request = BookPub::RDAS::Request::ProductPrice->GetRequestObject($serviceID);
        $ebookOnly = 1 unless ( $request->includePhysicalProducts() );
    }

    my $collection = BookPub::DB::Item::BookProduct->GetAllWithLimit(
        serviceID => $serviceID,
        ebookOnly => $ebookOnly,
        limit     => $limit,
        order     => 'DESC',
        current   => $current
    );

    Log->debug("* Get list of all products");

    my @list;

    while ( my $dbitem = $collection->next() ) {
        push( @list, new BookPub::Catalog::Product::Book( dbItem => $dbitem ) );
    }

    return @list;
}

sub _checkFailure {
    my $self      = shift;
    my $productID = shift;
    my $serviceID = shift;

    assert($serviceID);
    assert($productID);

    my $failure = new BookPub::RDAS::Form::ProductMonitor::ProductMonitorItem::Failure( productID => $productID, serviceID => $serviceID );

    return $failure->Failure();
}

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

    my $service = BookPub::DB::Item::Service->Lookup( service_id => $serviceID );

    unless ($service) {
        BookPub::Tracker::Service::AddService( service_id => $serviceID );
        $service = BookPub::DB::Item::Service->Lookup( service_id => $serviceID );
    }

    die "Unknown Service ID: $serviceID" unless ($service);

    return $service->service_name();
}

1;
