package FS::Cron::pay_batch;

use strict;
use vars qw( @ISA @EXPORT_OK $me $DEBUG );
use Exporter;
use Date::Format;
use FS::UID qw(dbh);
use FS::Record qw( qsearch qsearchs );
use FS::Conf;
use FS::queue;
use FS::agent;

@ISA = qw( Exporter );
@EXPORT_OK = qw ( pay_batch_submit pay_batch_receive );
$DEBUG = 0;
$me = '[FS::Cron::pay_batch]';

#freeside-daily %opt:
#  -v: enable debugging
#  -l: debugging level
#  -m: Experimental multi-process mode uses the job queue for multi-process and/or multi-machine billing.
#  -r: Multi-process mode dry run option
#  -a: Only process customers with the specified agentnum

sub pay_batch_submit {
  my %opt = @_;
  local $DEBUG = ($opt{l} || 1) if $opt{v};
  # if anything goes wrong, don't try to roll back previously submitted batches
  local $FS::UID::AutoCommit = 1;
  
  my $dbh = dbh;

  warn "$me batch_submit\n" if $DEBUG;
  my $conf = FS::Conf->new;

  # need to respect -a somehow, but for now none of this is per-agent
  if ( $opt{a} ) {
    warn "Payment batch processing skipped in per-agent mode.\n" if $DEBUG;
    return;
  }
  my %gateways;
  foreach my $payby ('CARD', 'CHEK') {
    my $gatewaynum = $conf->config("batch-gateway-$payby");
    next if !$gatewaynum;
    my $gateway = FS::payment_gateway->by_key($gatewaynum)
      or die "payment_gateway '$gatewaynum' not found\n";

    if ( $gateway->batch_processor->can('default_transport') ) {

      foreach my $pay_batch ( 
        qsearch('pay_batch', { status => 'O', payby => $payby }) 
      ) {

        warn "Exporting batch ".$pay_batch->batchnum."\n" if $DEBUG;
        eval { $pay_batch->export_to_gateway( $gateway, debug => $DEBUG ); };

        if ( $@ ) {
          # warn the error and continue. rolling back the transaction once 
          # we've started sending batches is bad.
          warn "error submitting batch ".$pay_batch->batchnum." to gateway '".
          $gateway->label."': $@\n";
        }
      }

    } else { #can't(default_transport)
      warn "Payment gateway '".$gateway->label.
      "' doesn't support automatic transport; skipped.\n";
    }
  } #$payby

  1;
}

sub pay_batch_receive {
  my %opt = @_;
  local $DEBUG = ($opt{l} || 1) if $opt{v};
  local $FS::UID::AutoCommit = 0;

  my $dbh = dbh;
  my $error;

  warn "$me batch_receive\n" if $DEBUG;
  my $conf = FS::Conf->new;

  # need to respect -a somehow, but for now none of this is per-agent
  if ( $opt{a} ) {
    warn "Payment batch processing skipped in per-agent mode.\n" if $DEBUG;
    return;
  }
  my %gateways;
  foreach my $payby ('CARD', 'CHEK') {
    my $gatewaynum = $conf->config("batch-gateway-$payby");
    next if !$gatewaynum;
    # If the same gateway is selected for both paybys, only import it once
    $gateways{$gatewaynum} = FS::payment_gateway->by_key($gatewaynum);
    if ( !$gateways{$gatewaynum} ) {
      $dbh->rollback;
      die "batch-gateway-$payby gateway $gatewaynum not found\n";
    }
  }

  foreach my $gateway (values %gateways) {
    if ( $gateway->batch_processor->can('default_transport') ) {
      warn "Importing results from '".$gateway->label."'\n" if $DEBUG;
      $error = eval { 
        FS::pay_batch->import_from_gateway( gateway =>$gateway, debug => $DEBUG ) 
      } || $@;
      if ( $error ) {
        # this we can roll back
        $dbh->rollback;
        die "error receiving from gateway '".$gateway->label."':\n$error\n";
      }
    } 
    # else we already warned about it above
  } #$gateway

  # resolve batches if we can
  foreach my $pay_batch (qsearch('pay_batch', { status => 'I' })) {
    warn "Trying to resolve batch ".$pay_batch->batchnum."\n" if $DEBUG;
    $error = $pay_batch->try_to_resolve;
    if ( $error ) {
      $dbh->rollback;
      die "unable to resolve batch ".$pay_batch->batchnum.":\n$error\n";
    }
  }

  $dbh->commit;
}
1;
