#!/usr/bin/perl
#
# Report all importers ever used, a file imported, the number of times used
# and the top client and count.
#
# 1. Grab all unique Service ID version pairs from the client file tables where
#    the file does not have a parent id (is an import not a split)
# 2. Gather the importer information from RPS::Sale::File table;
# 3. Query each client database to find a sample file and the importer counts.
#
# Limitation:
#
#   Because the importer used is not stored in the database this must be pulled
#   from code.  Therefore any changes to service/version pairs in code will
#   alter this report.
#

use strict;

use Getopt::Std;
use File::Basename;

my %opt;
usage() unless getopts( 'c:qhldv', \%opt );

if ( $opt{l} ) {
    list_clients( $ARGV[0] );
}

if ( $opt{h} ) {
    usage();
}

my $controller = new ImporterSample(
    client_id => $opt{c},
    filename  => $ARGV[0],
    quiet     => $opt{q},
    verbose   => $opt{v},
    debug     => $opt{d}
);

$controller->run();

sub usage {
    my $prog = basename $0;

    print <<EofUSAGE;

usage: $prog [-c client_id] [-l client_name/pattern] [-h] [-d]
            -c - Client ID (if not specified then run for all clients)
            -l - List client ids (host pattern is optional)
            -d - display debug information to STDERR
            -v - display verbose debug information to STDERR
            -q - Do not output summary report
            -h - display this screen
EofUSAGE

    exit 1;
}

sub list_clients {
    my $host = shift;
    my $key;
    foreach $key ( sort { $a <=> $b } keys(%Common::RSDB::CLIENT_DB) ) {
        printf( "%-20s %-10s ID: %s\n", $Common::RSDB::CLIENT_DB{$key}->{db_name}, "($Common::RSDB::CLIENT_DB{$key}->{host_id})", $key )
          if ( !defined($host) || $Common::RSDB::CLIENT_DB{$key}->{db_name} =~ /$host/i );
    }
    exit 1;
}

package DB::File;

use lib '/app/tools/raptor/lib';
use base 'Raptor::DB::Item::File';

use constant kTable => 'file';
use constant kDB    => Common::DB::Item::kClientDB();

sub Get {
    my $class = shift;
    my %args  = @_;
    my $dbo   = Common::RSApp::GetClientDB();

    my $sql =
        "SELECT * FROM file "
      . "WHERE service_id = $args{service_id} AND "
      . "version_num = $args{version_num} AND "
      . "parent_file_id IS NULL "
      . "ORDER by date_processed DESC LIMIT 1";

    my $sth = $dbo->DoCmd($sql);
    return $sth->fetchrow_hashref;
}

sub GetServiceCount {
    my $class = shift;

    my $dbo = Common::RSApp::GetClientDB();
    my $sql =
        "SELECT service_id, version_num, count(*) as count "
      . "FROM file "
      . "WHERE service_id IS NOT NULL and version_num IS NOT NULL "
      . "GROUP BY service_id, version_num";

    return $dbo->DoCmd($sql);
}

1;

package ImporterSample;

use Data::Dumper;
use Sys::Hostname;

use lib '/app/tools/common/lib';
use Common::RSApp;
use Common::Util;
use Common::Assert;
use Common::WriteXML;

use lib '/app/tools/common/lib';
use Common::Client;
use base 'Common::Script';

use lib '/app/tools/support/lib';
use Support::Service::ServiceSimple;

use lib '/app/tools/rps/lib';
use RPS::Import::Service;

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

    my %clients;

    $self->{_filename} = $args{filename};

    return $self;
}

sub run_process {
    my $self   = shift;
    my $infile = $self->_getFileHandle( $self->{_filename} );
    my $i      = 1;
    my @list;

    my $serviceData = $self->_getServiceData();

    print join( "\t",
        "Service",          "Version",   "Importer", "File",       "Physical Importer",
        "Physical Service", "Last Used", "Count",    "Top Client", "Top Count" )
      . "\n";

    foreach my $serviceID ( keys(%$serviceData) ) {
        foreach my $version ( keys( %{ $serviceData->{$serviceID} } ) ) {
            my $importer = $self->_getImporter( $serviceID, $version );
            my $history = $self->_getHistory( $serviceID, $version );

            print join( "\t",
                $self->_prettyService($serviceID),
                $version,
                $importer,
                $history->{file},
                $self->_isPhysicalImporter($importer),
                $self->_isPhysicalService($serviceID),
                $history->{last},
                $serviceData->{$serviceID}->{$version}->{count},
                $self->_prettyClient( $serviceData->{$serviceID}->{$version}->{topclient} ),
                $serviceData->{$serviceID}->{$version}->{topcount},
            ) . "\n";
        }
    }
}

sub _prettyClient {
    my $self     = shift;
    my $clientID = shift;

    my $singleton = new Common::RSApp( clientID => 0 );
    my $client = new Common::Client( clientID => $clientID );
    $singleton = undef;

    return $client->ClientName . " ($clientID)";
}

sub _prettyService {
    my $self      = shift;
    my $serviceID = shift;

    my $service = new Support::Service::ServiceSimple( serviceID => $serviceID );

    my $name = $service->ServiceName ? $service->ServiceName : "undef";
    return "$name ($serviceID)";
}

sub _getFileHandle {
    my $self = shift;
    my $filename = shift || return *STDIN;

    open( INFILE, $filename ) || die "Can't read input file: $filename ($!)";
    return *INFILE;
}

sub _getServiceData {
    my $self = shift;
    my @list = $self->_get_client_list();

    foreach my $client (@list) {
        my $singleton = new Common::RSApp( clientID => $client );
        my $data = $self->_getClientServiceData($client);
    }

    return $self->{_serviceData};
}

sub _getClientServiceData {
    my $self     = shift;
    my $client   = shift;
    my $clientID = Common::RSApp::GetClientID();

    my $data = $self->{_serviceData};

    my $sth = DB::File->GetServiceCount();

    while ( my $row = $sth->fetchrow_hashref() ) {
        my $service = $row->{service_id};
        my $version = $row->{version_num};

        if ( defined($service) && defined($version) ) {
            $data->{$service}->{$version}->{count} += $row->{count};

            if ( $data->{$service}->{$version}->{topclient} ) {
                if ( $data->{$service}->{$version}->{topcount} < $row->{count} ) {
                    $data->{$service}->{$version}->{topclient} = $clientID;
                    $data->{$service}->{$version}->{topcount}  = $row->{count};
                }
            } else {
                $data->{$service}->{$version}->{topclient} = $clientID;
                $data->{$service}->{$version}->{topcount}  = $row->{count};
            }
        }
    }

    $self->{_serviceData} = $data;

}

sub _getImporter {
    my $self      = shift;
    my $serviceID = shift;
    my $version   = shift;

    return unless ( $serviceID && $version );

    my $importers = RPS::Import::Service::GetImporters($serviceID);
    return $importers->{$version};
}

sub _getHistory {
    my $self      = shift;
    my $serviceID = shift;
    my $version   = shift;
    my @list      = $self->_get_client_list();

    my $history;

    return unless ( $serviceID && $version );

    foreach my $client (@list) {
        my $singleton = new Common::RSApp( clientID => $client );

        my $tmp = $self->_getClientHistory( $serviceID, $version );
        next unless ($tmp);

        if ($history) {
            if ( $history->{last} gt $tmp->{last} ) {
                $history = $tmp;
            }
        } else {
            $history = $tmp;
        }

        $singleton = undef;
    }

    return $history;
}

sub _getClientHistory {
    my $self      = shift;
    my $serviceID = shift;
    my $version   = shift;
    my $clientID  = Common::RSApp::GetClientID();
    my $history;

    my $file = DB::File->Get( service_id => $serviceID, version_num => $version );

    if ($file) {
        if ($file) {
            $history->{client_id} = $clientID;
            $history->{file}      = $file->{file_dir} . "/" . $file->{file_name};
            $history->{last}      = $file->{date_processed};
        }
    }

    return $history;
}

sub _get_client_list {
    my $self = shift;
    my @list;

    my $host = hostname;
    $host =~ s/\..*//g;
    $self->debug("Running on $host");

    assert($self);
    assert($host);
    my $singleton = new Common::RSApp( clientID => 0 );

    return ( $self->{_client_id} ) if ( defined( $self->{_client_id} ) );

    # If this is being run on a production box
    if (Common::RSApp::IsProductionServer) {
        return sort { $a <=> $b } Common::RSDB::GetAllRPSClientIDs();
    }

    # Running on some other host, run of all install DBs on localhost
    else {
        return sort { $a <=> $b } Common::RSDB::GetLocalClientIDs($host);
    }
}

sub _isPhysicalImporter {
    my $self     = shift;
    my $importer = shift;

    my @physicalImporters = qw( RPS::Import::ADAPhys
      RPS::Import::AmazonCreateSpace
      RPS::Import::AmazonPhys
      RPS::Import::BMG
      RPS::Import::BMGCHouse
      RPS::Import::BMGSony2
      RPS::Import::BMGSonyPhys
      RPS::Import::BMGSonyPhys2
      RPS::Import::Caroline
      RPS::Import::CreateSpace
      RPS::Import::Dock
      RPS::Import::DownloadCentric
      RPS::Import::DTArtistDirect
      RPS::Import::DTInternational
      RPS::Import::DTThirdParty
      RPS::Import::Echo
      RPS::Import::Echospin
      RPS::Import::Faithworks
      RPS::Import::Fontana
      RPS::Import::Fusion
      RPS::Import::HarmoniaMundi
      RPS::Import::KochEntCanada
      RPS::Import::KochPhysArc
      RPS::Import::LMMGSales
      RPS::Import::LookoutDirect
      RPS::Import::Navarre
      RPS::Import::NugsRevised
      RPS::Import::OutSideMusic
      RPS::Import::ProperUK
      RPS::Import::Red
      RPS::Import::RevolverPhysical
      RPS::Import::Rootsy
      RPS::Import::RoughTradeDist
      RPS::Import::RoughTradeDist2
      RPS::Import::RSFormat
      RPS::Import::RSFormatFull
      RPS::Import::RSPhysicalFormat
      RPS::Import::Rykodisc
      RPS::Import::Rykodisc2
      RPS::Import::SanctHistorical
      RPS::Import::SDROutsideSales
      RPS::Import::Shellshock
      RPS::Import::TouchNGoPhys
      RPS::Import::UniversalCAPhysical
      RPS::Import::Welk );

    return grep( /^$importer$/, @physicalImporters ) ? "P" : "";
}

sub _isPhysicalService {
    my $self = shift;
    my $serviceID = shift || return;

    my @services = qw( 46 47 48 49 50 51 54 55 56 57 58 59 61 63 64 66 78 139
      140 155 156 160 170 172 174 256 275 277 282 350 );

    return grep( /^$serviceID$/, @services ) ? "X" : "";
}

1;
