#!/usr/bin/perl

use strict;
use Getopt::Std;
use Date::Format qw(time2str);
use File::Temp qw(tempdir); #0.19 for ->newdir() interface, not in 5.10.0
use Net::FTPSSL;
use FS::UID qw(adminsuidsetup dbh);
use FS::Record qw(qsearch qsearchs);
use FS::pay_batch;
use FS::Conf;

use vars qw( $opt_v $opt_a $opt_f $opt_n );
getopts('va:f:n');

#$Net::SFTP::Foreign::debug = -1;
sub usage { "
  Usage:
      freeside-rbc-download [ -v ] [ -n ] [ -a archivedir ] [ -f filename ] user\n
" }

sub debug {
  print STDERR $_[0] if $opt_v;
}

my $user = shift or die &usage;
adminsuidsetup $user;

$FS::UID::AutoCommit = 0;
my $dbh = dbh;

if ( $opt_a ) {
  die "no such directory: $opt_a\n"
    unless -d $opt_a;
  die "archive directory $opt_a is not writable by the freeside user\n"
    unless -w $opt_a;
}

my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere?

my $conf = new FS::Conf;
my ($username, $password) = $conf->config('batchconfig-RBC-login');
$username and $password
  or die "RBC FTP login not configured. Enter your username and password in 'batchconfig-rbc-login'.\n";

my $host = 'ftpssl.rbc.com';
debug "Connecting to $username\@$host...\n";

my $ftp = Net::FTPSSL->new($host,
                           Timeout => 30,
                           Debug => ($opt_v ? 1 : 0),
                           Croak => 1, # rely on auto-rollback when dbh closes
                          );
$ftp->login($username, $password);

# directory layout:
# ~/                          # upload to here
# ~/inbound
# ~/inbound/valid             # batches move here while being processed
# ~/outbound
# ~/outbound/XXXX             # string of four characters; results arrive here

$ftp->cwd('outbound');
for my $dir ( $ftp->nlst ) {
  debug "Entering outbound/$dir\n";
  $ftp->cwd($dir);
  FILE: for my $filename ( $ftp->nlst ) {
    debug "$filename...";
    # filenames look like "RPT9999X.111".
    # 9999 is the four-digit report type
    # X is "P" for production or "T" for test
    # 111 is the sequential file number
    if ( $opt_f ) {
      if ( $filename ne $opt_f ) {
        debug "is not the requested file.\n";
        next FILE;
      }
      # -f can be used to download/process any file, even one that doesn't fit
      # the naming rule (e.g. those that are already downloaded).
    } elsif ( $filename =~ /^RPT(\d{4})[PT]\.\d{3}$/ ) {
      # fallthrough; don't currently reject files based on RPT type, because
      # our parser should be able to figure it out
    } else {
      debug "skipped.\n";
      next FILE;
    }

    debug "downloading.\n";
    $ftp->get($filename, "$tmpdir/$filename");

    #copy to archive dir
    if ( $opt_a ) {
      debug "Copying to archive dir $opt_a\n";
      system 'cp', "$tmpdir/$filename", $opt_a;
      warn "failed to copy $tmpdir/$filename to $opt_a: $!\n" if $!;
    }

    debug "Processing batch...";
    open(my $fh, '<', "$tmpdir/$filename")
      or die "couldn't read temp file: $!\n";

    my $error = FS::pay_batch->import_results(
      filehandle  => $fh,
      format      => 'RBC',
      no_close    => ($opt_n ? 1 : 0),
    );

    if ( $error ) {
      die "Processing $filename failed:\n$error\n\n";
    }

    debug "done.\n";
  } # FILE
  $ftp->cdup();
} # $dir

debug "Finished.\n";
dbh->commit;
exit(0);

=head1 NAME

freeside-rbc-download - Retrieve payment batch responses from RBC.

=head1 SYNOPSIS

  freeside-rbc-download [ -v ] [ -f filename ] [ -a archivedir ] user

=head1 DESCRIPTION

Command line tool to download payment batch responses from the Royal Bank of 
Canada ACH service. These files are fixed-width data files containing some
combination of valid, returned, or reversed payment records.

By default, the script will download any files with names like "RPT9999X.111"
where 9999 is a four-digit document type code (like "0900", all records), X is
the letter "P" for production or "T" for test mode, and 111 is a counter
incremented with each new response file. After the files are downloaded, RBC's
server will automatically rename them with the suffix '.downloaded%FTPS' to 
avoid double-processing them.


-v: Be verbose.

-f filename: Download a file with a specific name, instead of all files 
matching the pattern. This can be used to reprocess a specific file.

-a directory: Archive the files in the specified directory.

-n: Do not try to close batches after applying results.

user: freeside username

=head1 BUGS

=head1 SEE ALSO

L<FS::pay_batch>

=cut

1;

