#!/usr/bin/perl

use strict;
use warnings;
use File::Find qw( find );
use FindBin qw( $Bin );
use lib "$Bin/../../lib";
use POSIX qw( strftime );
use Data::Dumper;
use Date::Calc qw( Days_in_Month );
use App::POS::Config;
use Email::Send::SMTP::Gmail;
use DBI;
use App::POS::DB::Postgres;

my $cfg = App::POS::Config->new( file => "/opt/pos/etc/config.ini" );
my $info = $cfg->load();

my $dsn = 'DBI:Pg:dbname=pos;host=127.0.0.1';
my $user = 'root';
my $passwd = '';

my $db = App::POS::DB::Postgres->new(dbh => DBI->connect($dsn,$user,$passwd,{}));

my $DOC_TYPE_SERIE = $info->{DOC_TYPE_SERIE} || "";
my $year_str = &strftime("%Y", localtime);
$DOC_TYPE_SERIE =~ s/\@YEAR\@/$year_str/g;
$DOC_TYPE_SERIE =~ s/\s//g;
$DOC_TYPE_SERIE =~ s/\///g;

my $LANG = $info->{LANG} || "";
$LANG = 'POS' if $LANG eq 'PT';
$LANG = 'SML' if $LANG eq 'AUDITOR';
my $SAFT_CompanyId = $info->{SAFT_CompanyId} || "";
my $SAFT_TaxRegistratioNumber = $info->{SAFT_TaxRegistratioNumber} || "";
my $SAFT_CompanyName = $info->{SAFT_CompanyName} || "";
my $SAFT_BusinessName = $info->{SAFT_BusinessName} || "";
my $SAFT_AddressDetail = $info->{SAFT_AddressDetail} || "";
my $SAFT_City = $info->{SAFT_City} || "";
my $SAFT_PostalCode = $info->{SAFT_PostalCode} || "";
my $INTERNET_SEND_EMAILS = $info->{INTERNET_SEND_EMAILS} || 0;
my $INTERNET_GMAIL_LOGIN = $info->{INTERNET_GMAIL_LOGIN} || "";
my $INTERNET_GMAIL_PASSWORD = $info->{INTERNET_GMAIL_PASSWORD} || "";
my $INTERNET_SEND_DAILY_Z = $info->{INTERNET_SEND_DAILY_Z} || "";
my $INTERNET_SEND_MONTHLY_Z = $info->{INTERNET_SEND_MONTHLY_Z} || "";
my $INTERNET_REPORT_FORMAT = $info->{INTERNET_REPORT_FORMAT} || "pdf";

if (! $INTERNET_SEND_EMAILS) {
  die "Internet email sending is disabled (INTERNET_SEND_EMAILS)...";
}

if (! $INTERNET_GMAIL_LOGIN || ! $INTERNET_GMAIL_PASSWORD) {
  die "Gmail login and password must be defined (INTERNET_GMAIL_LOGIN, INTERNET_GMAIL_PASSWORD)...";
}

if ($INTERNET_SEND_MONTHLY_Z) {
  monthly_z($INTERNET_REPORT_FORMAT);
}

if ($INTERNET_SEND_DAILY_Z) {
  daily_z($INTERNET_REPORT_FORMAT);
}

# give Handlers time to product the PDFs
sleep 240;

send_emails();

sub send_emails {
  if (! -d "/opt/pos/common/data/emails_to_send") {
    system("mkdir -p /opt/pos/common/data/emails_to_send");
  }

  my @to_delete = ();

  find( sub {
    return unless -f $File::Find::name;

    my $tmp = $_;
    $tmp =~ s/\..*?$//; # remove file extension
    my @t = split /_/, $tmp;
    return unless scalar @t == 4;

    my $to = "";

    # try to define the mail destination
    if ($t[0] eq 'report' && $t[1] eq 'detailed') {
      # daily detailed 
      if ($t[2] eq $t[3] && $INTERNET_SEND_DAILY_Z) {
        $to = $INTERNET_SEND_DAILY_Z;
      }
      # monthly detailed
      else {
        $to = $INTERNET_SEND_MONTHLY_Z if $INTERNET_SEND_MONTHLY_Z;
      }
    }

    if (! $to) {
      print STDERR "Can't find mail destination for file $_\n";
      return;
    }
    
    eval {
      my $email_obj = Email::Send::SMTP::Gmail->new(
        -smtp => 'smtp.gmail.com',
        -login => $INTERNET_GMAIL_LOGIN,
        -pass => $INTERNET_GMAIL_PASSWORD,
      );

      my @attachments = ( $File::Find::name );

      $email_obj->send(
        -to => $to,
        -subject=> "[$LANG FILE] $SAFT_TaxRegistratioNumber / SERIE $DOC_TYPE_SERIE - $_",
        -body=> "$LANG FILE\n=========\n\n$_\n",
        -attachments=>join(",", @attachments),
      );
    };

    if ($@) {
      print STDERR "Error sending $_ by email : $@";
      return;
    }

    push @to_delete, $File::Find::name;
  }, ( "/opt/pos/common/data/emails_to_send" ) );

  for (@to_delete) {
    unlink $_;
  }
}

sub monthly_z {
  my( $format ) = @_;
  my( $from, $to ) = dates_guess();

  my( $ctrl_year, $ctrl_month ) = $from =~ /^(\d+)\-(\d+)\-/;

  my $ctrl_dir = "/opt/pos/common/data/reports_to_network/monthly/$ctrl_year/$ctrl_month";
  system("mkdir -p $ctrl_dir") unless -d $ctrl_dir;

  if (-e $ctrl_dir."/".$from."_".$to.".txt") {
    print STDERR "This month was generated already, ignoring...\n";
    return;
  }

  my $c = $db->select(qq{
    SELECT id
    FROM clerks
    WHERE deleted = 0 AND (used_for_training = 1 OR can_daily_totals = 1 OR can_close_day = 1) 
    ORDER BY used_for_training DESC
    LIMIT 1
  });

  die "Can't find a suitable clerk (used_for_training, can_daily_totals, can_close_day)"
    unless scalar @$c;

  my $clerk_id = $c->[0]->{id};

  my $pdf = $format eq 'pdf' ? 1 : 0;
  my $xls = $format eq 'xls' ? 1 : 0;
  my $file = "/opt/pos/common/tmp/report#detailed#$from#$to#0#$clerk_id#$pdf#0#$xls#nocustom#1.txt";

  open(F, "> $file");
  print F "1\n";
  close(F);

  open(F, "> ".$ctrl_dir."/".$from."_".$to.".txt");
  print F "1\n";
  close(F);
}

sub daily_z {
  my( $format ) = @_;
  my $date = &strftime("%Y-%m-%d", localtime);

  if (-e "/opt/pos/.business_date") {
    local $/ = undef;
    open(F, "< /opt/pos/.business_date");
    my $cnt = <F>;
    chop($cnt);
    close(F);
    $date = $cnt if $cnt;
  }

  my( $ctrl_year, $ctrl_month ) = $date =~ /^(\d+)\-(\d+)\-/;
  my $ctrl_dir1 = "/opt/pos/common/data/reports_to_network/daily/execute_control/$ctrl_year/$ctrl_month";
  my $ctrl_dir2 = "/opt/pos/common/data/reports_to_network/daily/send_control/$ctrl_year/$ctrl_month";
  system("mkdir -p $ctrl_dir1") unless -d $ctrl_dir1;
  system("mkdir -p $ctrl_dir2") unless -d $ctrl_dir2;

  if (-e $ctrl_dir1."/".$date.".txt") {
    print STDERR "We executed daily today already, skipping...\n";
    return;
  }

  my $c = $db->select(qq{
    SELECT id
    FROM clerks
    WHERE deleted = 0 AND (used_for_training = 1 OR can_daily_totals = 1 OR can_close_day = 1) 
    ORDER BY used_for_training DESC
    LIMIT 1
  });

  die "Can't find a suitable clerk (used_for_training, can_daily_totals, can_close_day)"
    unless scalar @$c;

  my $clerk_id = $c->[0]->{id};

  $c = $db->select(qq{
    SELECT DISTINCT(business_date)
    FROM sales_hashes
    ORDER BY business_date DESC
    LIMIT 5
  });

  my $pdf = $format eq 'pdf' ? 1 : 0;
  my $xls = $format eq 'xls' ? 1 : 0;

  for (@$c) {
    if ($_->{business_date} eq $date) {
      print STDERR $_->{business_date}." is current work date, skipping...\n";
    }
    else {
      my $date_f = $_->{business_date};

      if (-e $ctrl_dir2."/$date_f.txt") {
        print STDERR "Report for date $date_f was done already, skipping...\n";
        next;
      }

      my $file = "/opt/pos/common/tmp/report#detailed#$date_f#$date_f#0#$clerk_id#$pdf#0#$xls#nocustom#1.txt";

      open(F, "> $file");
      print F "1\n";
      close(F);

      open(F, "> ".$ctrl_dir2."/$date_f.txt");
      print F "1\n";
      close(F);
    }
  }

  open(F, "> ".$ctrl_dir1."/$date.txt");
  print F "1\n";
  close(F);
}

sub dates_guess {
  my $y = &strftime("%Y", localtime);
  my $m = &strftime("%m", localtime);

  if ($m eq '01') {
    $m = 12;
    $y--;
  }
  else {
    $m = $m*1;
    $m = sprintf("%02d", --$m);
  }

  my $days = Days_in_Month($y,$m);
  return ( "$y-$m-01", "$y-$m-$days" )
}

