#!/usr/bin/perl

use strict;
use CGI;
use JSON;

use Opals::Context;

use SIP::Map;
use SIP::Template;
use SIP::Session;
use SIP::Utility;

my $dbh = Opals::Context->dbh();
END { $dbh->disconnect(); }

my $cgi = CGI->new;

# $cgi->param('aaa') returns an array of aaa
my $input = $cgi->Vars();

#my $op = $input->{'op'};
my $util = SIP::Utility->new();

my $template = SIP::Template->new(filename => 'check_in.tmpl',);

my ($ok, $resensitize, $alert, $alert_type, $patron_identifier, $hold_patron) =
  (
  'false', 'false',
  'false', SIP::Map::ALERT_TYPE->{'undetermined'},
  '', SIP::User->new(dbh => $dbh)
  );

my $transaction_datetime = $util->now();

my $barcode = $input->{'item_identifier'};

my $session = SIP::Session->new(
  dbh             => $dbh,
  session_id      => $input->{'session_id'},
  item_identifier => $barcode
);
$session->validate(item_identifier => 1);

my $screen_message = $session->get('screen_message');
my $record         = $session->get('record');

if ($session->isValid()) {
  my @val = ();

  # cancel previous failed checkout
  if ($input->{'cancel'} eq 'Y') {
    @val = ($barcode);
    $dbh->do(<<_SQL_, undef, @val);
update  opl_loan
set     dateReturn = dateLoan
where   barcode = ?
     && dateReturn is null
_SQL_
  }
  else {
    # excluded from param: duedate, command, loanType.
    my $response = $util->post(
      url   => "http://$ENV{'HTTP_HOST'}/bin/ajax/circ/return",
      param => [
        sip_sid => $input->{'session_id'},
        bcList  => $barcode,
      ]
    );

#    open CI, '>>/tmp/ctho.sip_ci';
#    my $c = $response->content;
#    print CI <<_CI_;
#url   => "http://$ENV{'HTTP_HOST'}/bin/ajax/circ/return",
#param => [
#  sip_sid => $input->{'session_id'},
#  bcList  => $barcode,
#]
#$c
#_CI_
    if ($response->is_success) {
      my $c = $response->content;
      $c =~ s/\\'/'/g;
      my $r      = decode_json $c;
      my $return = $r->{'return'}->[0];
      if ($return->{'lid'} > 0) {
        $ok          = 'true';
        $resensitize = 'true';

        my $hold_uid = $return->{'placeHoldForUser'}->{'uid'};
        if ($hold_uid > 0) {
          $hold_patron->setInfo(uid => $hold_uid);

          $alert_type = SIP::Map::ALERT_TYPE->{'hold_for_this_library'};
        }

        my ($charge_overdue) = $dbh->selectrow_array(<<_SQL_);
select  val
from    opl_preference
where   var='charge_overdue'
_SQL_

        my $odl_id = $return->{'odlInfo'}->{'overdue'}->{'odl_id'};

        my $overdue = $return->{'odlInfo'}->{'overdue'};
        my $unit = $overdue->{'daysOverdue'} || $overdue->{'hoursOverdue'};

        if ($charge_overdue && $odl_id && $unit) {
          my $fr = _getFineRate($dbh, $return->{'bibInfo'}->{'itemType'});
          my $rate = $fr->{'overdue'} || $fr->{'overduePerHour'};

          my $chargeAmount = $unit * $rate;
          $chargeAmount =
            ($chargeAmount < $fr->{'maxOverdue'})
            ? $chargeAmount
            : $fr->{'maxOverdue'};

          _setCharge($util, $return->{'uid'}, $odl_id, $rate, $unit,
            $chargeAmount);
        }
      }
      else {
        $screen_message = 'Please see library staff for assitance.';

        #$screen_message = "Error: $return->{'retStatusCode'}.";
      }
    }
    else {
      $screen_message = 'Error: '.$response->status_line.'.';
    }
  }
}

$alert = 'true' if ($alert_type ne SIP::Map::ALERT_TYPE->{'undetermined'});

my $response = {
  debug            => $session->get('debug'),
  ok               => $ok,
  resensitize      => $resensitize,
  magnetic_media   => SIP::Map::MAP->{ $record->{'type'} }->{'magnetic_media'},
  alert            => $alert,
  transaction_date => $util->format_datetime($transaction_datetime, 'SIP'),
  institution_id   => $input->{'institution_id'},
  item_identifier  => $barcode,
  permanent_location   => $record->{'location'},
  media_type           => SIP::Map::MAP->{ $record->{'type'} }->{'media_type'},
  title_identifier     => $record->{'title'},
  patron_identifier    => $patron_identifier,
  collection_code      => $record->{'collection_code'},
  call_number          => $record->{'call_number'},
  destination_location => $record->{'location'},
  alert_type           => $alert_type,
  hold_patron_ID       => $hold_patron->getPatronIdentifier(),
  hold_patron_name     => $hold_patron->getPersonalName(),
  screen_message       => $screen_message,
};

$template->param($response);

$template->write(cgi => $cgi);

################################################################################
sub _setCharge {
  my ($util, $uid, $odl_id, $rate, $unit, $chargeAmount) = @_;

  my $param = {
    fineList => [
      {
        type         => 'overdue',
        uid          => $uid,
        odl_id       => $odl_id,
        rate         => $rate,
        unit         => $unit,
        waived       => 0.00,
        note         => 'Charged by SIP',
        chargeAmount => $chargeAmount,
      }
    ]
  };

  $util->post(
    url   => "http://$ENV{'HTTP_HOST'}/bin/ajax/billing/saveFine",
    param => encode_json $param
  );
}

############################################################
sub _getFineRate {
  my ($dbh, $itemType) = @_;

  my @val = ($itemType);
  my $fr = $dbh->selectrow_hashref(<<_SQL_, undef, @val);
select  overdue, overduePerHour, maxOverdue
from    opl_fineRate
where   itemType = ?
_SQL_

  foreach my $k (keys %{$fr}) {
    $fr->{$k} = 0 unless $fr->{$k};
  }

  return $fr;
}
