#!/usr/bin/perl

use File::Basename;

$SVNBASE=qq|$ENV{HOME}|;

$mailer = "mutt -i /dev/null -x -s '%s' -a '%s' -- '%s' < /dev/null";

# allow users to override the SVNBASE
require "$ENV{HOME}/.process_pay.conf" if -f "$ENV{HOME}/.process_pay.conf";

# this path is fixed
$SVNBASE .= "/finances/rapports-paie/";

require "$SVNBASE/process_pay.conf";

$SVNDEPOT = $SVNBASE . $YEAR;

# where the files have been downloaded.
$spool = $1;
if (!$spool) {
  $spool = $ENV{PWD};
}

print qq|
< << <<< Crude desjardins pay processing assistant, welcome! >>> >> >

This will assist you with various tedious tasks. I expect to find some
.pdf files extracted from the Desjardins service in the current
directory (or the directory you gave me as an argument). I will process
them, place them in SVN and commit them, mail them to the right users
and then finish.

Configuration for this script is in the script itself so edit it with a
text editor to change the following parameters:

SVNDEPOT: $SVNDEPOT
SPOOL: $spool
COMPANY: $COMPANY

Press ENTER to continue or control-c to abort.
|;

<STDIN>;

# from here on, we assume that PWD is the SVN repository
chdir("$SVNDEPOT") or die "can't cd into SVNDEPOT\n";

$| = 1;

$processed_stubs = 0;

# files to garbage-collect at the end
@delete_files = ();

# look for incomplete processes
foreach my $stub (`svn stat`) {
  chomp($stub);
  if ($stub =~ m#\s*A\s+(RP_${COMPANY}_\d+_\d+)\s*$#) {
    warn("committing parent dir $1\n");
    system("svn commit -m'commit parent dir' -N $1") == 0
      or warn("failed to commit $1\n");
  } elsif ($stub =~ m#\s*A\s+(RP_${COMPANY}_\d+_\d+/RELEVE_PAIE_.*\.pdf)\s*$#) {
    warn("found unprocessed stub, processing $1");
    process_stub($1);
  }
}

# look for zip files matchin the pattern in the spool directory
foreach my $file (glob("$spool/RP_${COMPANY}_*.zip")) {
  process_zipfile($file);
}

# check the directory again to see if there's anything left to commit that's not a stub
@found_stub = ();
@found_dirs = ();
foreach my $entry (`svn stat`) {
  chomp($entry);
  if ($entry =~ m#\s*A\s+(RP_${COMPANY}_\d+_\d+/RELEVE_PAIE_.*\.pdf)\s*$#) {
    push @found_stub, $1;
  } elsif ($entry =~ m#\s*A\s+(RP_${COMPANY}_\d+_\d+/.*)$#) {
    push @other_files, $1;
  }
}

if ($#found_stub >= 1) {
  warn("stubs still left: @found_stub\n");
}

if ($#other_files >= 1) {
  warn("committing remaining files\n");
  system("svn commit -m'automatically commit other pay files' @other_files") == 0
    or warn("couldn't commit other files");
}

warn("cleaning up .gpg files...\n");
foreach my $file (@delete_files) {
  unlink($file);
}

# process a group of stubs, which are zip files of PDF files
sub process_zipfile($) {
  my $stubs = shift;
  if (!-e $stubs) {
    warn("cannot find stub $stubs");
    return;
  }
  # list the content of the file and ask confirmation
  print "zip file found, content:\n";
  system("unzip -l \"$stubs\"");
  print "Process $stubs? ";
  <STDIN> =~ m/y(es)?/i || return;

  $dir = basename($stubs);
  $dir =~ s/.zip$//;
  system("unzip -d '$dir' -n '$stubs'") == 0
    or warn("cannot unzip $stubs\n");

  # add the directory to svn
  system("svn add -N '$dir'") == 0
      or warn("cannot add $dir to svn\n");

  # iterate over the files in the archive
  foreach my $stub (glob("$dir/RELEVE_PAIE_*.pdf")) {
      process_stub($stub);
  }
  warn("removed file $stubs\n");
  unlink($stubs);
}

sub process_stub($) {
    $stub = shift;
      $report = basename($stub);
      if ($report =~ m/RELEVE_PAIE_\d+_0*(\d+)_\d+_\d+.pdf/) {
          $employee_id = $1;
          # Silently ignore stubs that are not configured.
          if (! defined($EMPLOYEES{$employee_id})) {
              print "Stub \"$stub\" for employee $employee_id is not configured. Ignoring pay stub.";
              return;
          }
          $employee = $EMPLOYEES{$employee_id};
      }
      print "found paycheck \"$stub\" for employee $employee_id ($employee), proceed? ";
      if (<STDIN> =~ m/y(es)?/i) {
	# the actual attachment sent by email, might be different from
	# the stub if compressed, crypted, etc. (for now we just crypt)
	my $attach = $stub;
	# try to encrypt but fail gracefully
	if (system("gpg -r \"$employee\" -e \"$stub\"") == 0) {
	  $gpg = 1;
	  $attach .= '.gpg';
	} else {
	  $gpg = 0;
	  unlink("$stub.gpg");
	  warn("can't crypt the attachment, mailed in plain text\n");
	}
	# send the thing by email
        $mail_cmd = sprintf($mailer, ("Paycheck $stub", $SVNDEPOT . '/' . $attach, $employee));
        if (system($mail_cmd) == 0) {
            system("svn commit -m'automatic commit of stub for $employee' $stub") == 0
                or warn("failed to commit the stub $stub\n");
        } else {
            warn("can't send stub by email, not committed\n");
        }
	# remove the crypted file if created
	$gpg && push(@delete_files, "$stub.gpg");
      }
}
