#!/usr/bin/perl
# Script to show and/or set Orchard client configuration settings.
#
# To show settings for a specific Orchard-enabled client:
#    ./config_orchard.pl -c 202 --list
#
# To show settings for all clients:
#    ./config_orchard.pl --list
#
# To set the user_id for Orchard notifications:
#
#    ./config_orchard.pl -c 202 -u 316
#
# To configure a client to scan for quarterly reports:
#
#    ./config_orchard.pl -c 202 --quarterly
#    Note: client's Orchard account MUST be configured the same
#    way in OWS or you will not be able to retrieve any reports.
#
# To configure a client to not scan for any reports:
#
#    ./config_orchard.pl -c 202 -s 0
#
# To enable report generation requests for any missing reports:
#
#    ./config_orchard.pl -c 202 -s 2
#    Note: any report requests will appear in OWS.  Make sure the
#    Orchard client is aware of this before enabling this option.
#
# To check for existing reports only (no report generation requests
# will be submitted with this option, so the reports must be
# generated in OWS):
#
#    ./config_orchard.pl -c 202 -s 1
#
# To set the starting scan period for a client:
#
#    ./config_orchard.pl -c 202 -p 200
#    (sets the starting period as August 2015)
#
# Run with "-h" option for additional info.
#
use strict;
use Data::Dumper;

use strict;
use warnings;

use lib '/app/tools/common/lib';
use Common::RSApp;
use Common::DB::Item::OrchardClient;
use Common::OrchardFetcher::OrchardPeriod;

use Getopt::Long;
use File::Basename;

my %args;
parseCommandLine( \%args );
my $clientID     = $args{client_id};
my $userID       = $args{user_id};
my $showSettings = $args{list};

# Scan option.  Configures an Orchard client and how it will interact
# with the Orchard accounting statement API.
#
# 0 = no scan
# 1 = check and download report only if they already exist
# 2 = scan and submit report generation request if no report found (this
#     last option will show up on the client's OWS; use only with the client's
#     permission).
#
my $scanOption  = $args{scan_mode};
my $schedule    = $args{schedule};
my $startPeriod = $args{start_period};

my $appSingleton =
  ($clientID)
  ? Common::RSApp->new( clientID => $clientID )
  : Common::RSApp->new( clientID => 0 );

my $cdbo = Common::RSApp::GetCommonDB();
my $dbh  = $cdbo->DBH;

my $o;
if ($clientID) {
    $o = Common::DB::Item::OrchardClient->Lookup( client_id => $clientID );
    die("$clientID NOT A VALID ORCHARD CLIENT !!!") if ( !$o );
}

my %gPeriodInfo = Common::OrchardFetcher::OrchardPeriod::getPeriodHash();

if ($showSettings) {
    my @clients;
    if ($clientID) {
        push @clients, $o;
    } else {
        my $c = Common::DB::Item::OrchardClient->GetAll();
        while ( $c->hasNext() ) {
            push @clients, $c->next();
        }
    }

    foreach my $o (@clients) {
        my $email = getUserEmail( $o->user_id );

        my $name = getClientName( $o->client_id );

        print "##### Configuration for RPS client_id "
          . $o->client_id . " '"
          . getClientName( $o->client_id ) . "' "
          . " (Orchard account "
          . $o->account_id . ")\n";

        print "  Orchard notifications will be sent to user_id " . ( $o->user_id || 0 ) . " (" . $email . ")\n";

        my $scanType =
            ( $o->status == 0 ) ? 'No scan'
          : ( $o->status == 1 ) ? 'Read only'
          : ( $o->status == 2 ) ? 'Generate as needed'
          :                       'UNKNOWN';
        print "  Scan option is set to " . $o->status . " ($scanType)\n";

        my $schedType =
            ( $o->scan_schedule == 1 ) ? 'Monthly'
          : ( $o->scan_schedule == 2 ) ? 'Quarterly'
          :                              'UNKNOWN';

        print "  Scan schedule is set to " . $o->scan_schedule . " ($schedType)\n";

        my $startPeriod = $o->start_period;
        my $p           = _getPeriod($startPeriod);
        print "  Scans will start at period $startPeriod (" . $p->{start_date} . ")\n";

        print "\n";
    }

    exit;
}

unless ($clientID) { usage("ClientID required to change settings"); }

if ($userID) {
    my $email = getUserEmail($userID);
    $o->user_id($userID);
    $o->save();
    print "Client $clientID has been updated to send Orchard notifications to user_id $userID ($email)\n";
}

if ( defined $scanOption ) {
    if ( $scanOption =~ /^(0|1|2)$/ ) {
        my $old = $o->status;
        $o->status($scanOption);
        $o->save();
        print "Client $clientID scan status changed from $old to $scanOption\n";
    } else {
        print "Invalid scan option; valid values are 0 (no scan), 1 (read only) or 2 (generate if not found)\n";
    }
}

if ($schedule) {
    my $old = $o->scan_schedule;
    $o->scan_schedule($schedule);
    $o->save();
    print "Client $clientID scan schedule changed from $old to $schedule\n";
}

if ($startPeriod) {
    my $old = $o->start_period;
    $o->start_period($startPeriod);
    $o->save();
    print "Client $clientID start period changed from $old to $startPeriod\n";
}

### Subroutines below

sub getUserEmail {
    my $userID  = shift;
    my $sql     = "SELECT email FROM user WHERE user_id=$userID";
    my $sth     = $cdbo->DoCmd($sql);
    my ($email) = $sth->fetchrow_array();
    return $email || 'INVALID_USERID';
}

sub getClientName {
    my $clientID = shift;
    my $sql      = "SELECT client_name FROM client WHERE client_id=$clientID";
    my $sth      = $cdbo->DoCmd($sql);
    my ($name)   = $sth->fetchrow_array();
    return $name || 'NAME_NOT_FOUND';
}

sub parseCommandLine {
    my ($a) = @_;
    my $userID;
    my $clientID;
    my $list;
    my $monthly;
    my $quarterly;
    my $scan;
    my $schedule;
    my $startPeriod;
    my $help;

    die
      if (
        !GetOptions(
            'c|client=i'  => \$clientID,
            'u|user=i'    => \$userID,
            's|scan=i'    => \$scan,
            'p|period=s'  => \$startPeriod,
            'l|list'      => \$list,
            'm|monthly'   => \$monthly,
            'q|quarterly' => \$quarterly,
            'h|help'      => \$help,
        )
      );

    if ( $monthly && $quarterly ) {
        usage("Specify monthly or quarterly");
    }

    if ( $scan && $scan !~ /^(0|1|2)$/ ) {
        usage("Scan schedule must be 0 (ignore), 1 (read-only) or 2 (generate as needed)");
    }

    printHelp() if ($help);

    $schedule =
        ($quarterly) ? Common::OrchardFetcher::OrchardPeriod::kScanQuarterly
      : ($monthly)   ? Common::OrchardFetcher::OrchardPeriod::kScanMonthly
      :                undef;

    $a->{client_id}    = $clientID;
    $a->{user_id}      = $userID;
    $a->{list}         = $list;
    $a->{help}         = $help;
    $a->{schedule}     = $schedule;
    $a->{scan_mode}    = $scan;
    $a->{start_period} = $startPeriod;
}

sub usage {
    my $err = shift;
    print "ERROR: $err\n\n";
    print "$0 -c clientID [-u userID] [--list] [--quarterly|--monthly] [--scan (0|1|2)] [--period NNNN]\n";
    printHelp();
}

sub printHelp {
    print "------------------------------------------------------------------------------------\n";
    print "This script configures the Orchard client settings for an Orchard-enabled RPS client.\n";
    print "Arguments:\n\n";
    print "-l|--list      Shows the current setting for a client and exits.  Info for all clients\n";
    print "               will be shown if client_id not specified.\n";
    print "\n";
    print "-c clientID    Specifies the RPS client to be configured.  This must be a valid client\n";
    print "               in the RSCOMMON.orchard_client table.\n";
    print "\n";
    print "-u userID      Specifies the RPS user_id to receive Orchard notifications.  This must be\n";
    print "               a valid user_id in the RSCOMMON.user table.\n";
    print "\n";
    print "-s scanMode    Specifies how the Orchard sales fetcher will scan for sales reports:\n";
    print "               0 = do not scan for any reports; effectively halts any new file ingestion\n";
    print "               1 = scan for and download/ingest any existing reports\n";
    print "               2 = similar to 1, but submit report generation requests for missing reports\n";
    print "\n";
    print "-p period      Set the starting period for scans.  This should be a single period representing\n";
    print "               the month to start scanning (see RSCOMMON.orchard_period).  For quarterly\n";
    print "               clients, use the period for first month in the quarter.  E.g., use \"205\"\n";
    print "               rather than \"205,206,207\" to start scanning for sales on or after 1/1/2016.\n";
    print "\n";
    print "-m|--monthly   Query the Orchard API using monthly period identifiers\n";
    print "-q|--quarterly Query the Orchard API using quarterly period identifiers\n";
    print "               The Orchard client must be configured in Workstation as either monthly or\n";
    print "               quarterly, and the setting used here MUST match workstation.  If you try\n";
    print "               to scan using monthly reporting periods and the client is setup as\n";
    print "               quarterly in workstation, then you will not get any sales data.\n";
    exit;
}

sub _getPeriod {
    my $period = shift;
    my $pinfo;
    foreach my $id ( sort { $a <=> $b } keys %gPeriodInfo ) {
        $pinfo = $gPeriodInfo{$id};
        my $pid = $pinfo->{period};

        #my $pname = $pinfo->{period_name};
        #my $sdate = $pinfo->{start_date};
        #my $edate = $pinfo->{end_date};
        #print "[$id] period $pid name($pname) sdate($sdate) edate($edate)\n";
        return $pinfo if ( $pid eq $period );
    }
}

1;
