#!/usr/bin/perl

use strict;
use warnings;
use File::Path qw( make_path );
use File::Find qw( find );
use FindBin qw( $Bin );
use lib "$Bin/../../lib";
use POSIX qw( strftime );
use File::Copy qw( move );
use Data::Dumper;
use Date::Calc qw( Days_in_Month );
use DBI;

use App::POS::Config;
use App::POS::Utils qw(
  send_mail execution_dates emails_validate random_sleep file_modif_secs
  send_alert_to_ui
);
use App::POS::DB::Postgres;
use App::POS::Machine::Server;

my $mode = shift // "";

if ($mode eq 'cron') {
  my $sleep = random_sleep([10 .. 60]);
  print STDERR "$0> Will sleep $sleep seconds...\n";
  sleep $sleep;
}

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

if (exists $info->{STATION_NUMBER} && $info->{STATION_NUMBER} ne '0') {
  die "Must be executed in server machine...\n";
}

my $server = App::POS::Machine::Server->new( config => $cfg );
my $db = $server->database();

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 $STATION_NAME = $info->{STATION_NAME} || "";
my $SAFT_PostalCode = $info->{SAFT_PostalCode} || "";
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";
my $INTERNET_SEND_MAIL_HARDLOCK = $info->{INTERNET_SEND_MAIL_HARDLOCK} || "";

my %valid_formats = ( pdf => 1, xls => 1 );
die "Invalid email format...\n"
  if $INTERNET_REPORT_FORMAT && ! exists $valid_formats{ lc($INTERNET_REPORT_FORMAT) };

#my $LICENSED=`echo 1 | netcat localhost 8088 | grep LICENSED`;
#$LICENSED //= "";
#die "$LANG is in demo... aborting...\n" unless $LICENSED;

if ($INTERNET_SEND_MAIL_HARDLOCK) {
  my $MACHINE_ID=`$Bin/machine_id`;
  if ($MACHINE_ID ne $INTERNET_SEND_MAIL_HARDLOCK) {
    send_alert_to_ui('HARDLOCK ENVIO EMAIL ESTA ERRADO<BR>'.$INTERNET_SEND_MAIL_HARDLOCK);
    die "This machine has hardlock $MACHINE_ID and should have $INTERNET_SEND_MAIL_HARDLOCK, aborting...\n";
  }
}

my $control_file = "/tmp/.emails_send.running";

# removes control file if it's age is buffer than 60 minutes
my $secs = file_modif_secs($control_file);
unlink $control_file if $secs > 60*60;

if (-e "$control_file") {
  die "$control_file exists, aborting...\n";
}

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

if ($INTERNET_SEND_MONTHLY_Z) {
  die "Invalid email(s) found - $INTERNET_SEND_MONTHLY_Z\n"
    unless emails_validate($INTERNET_SEND_MONTHLY_Z);

  monthly_z($db, $INTERNET_REPORT_FORMAT);
}

if ($INTERNET_SEND_DAILY_Z) {
  die "Invalid email(s) found - $INTERNET_SEND_DAILY_Z\n"
    unless emails_validate($INTERNET_SEND_DAILY_Z);

  daily_z($db, $INTERNET_REPORT_FORMAT);
}

unlink $control_file;

#
# Functions
#

sub monthly_z {
  my $db = shift;
  my $format = shift;

  print STDERR "monthly_z()\n";
  print STDERR "\tdebug 0\n";

  #my $max_date = $db->select("SELECT MAX(business_date) AS date FROM sales_headers");
  my $max_date = $db->select("SELECT NOW()::date AS date");
  return unless scalar @$max_date;

  my( $from, $to ) = dates_guess($max_date->[0]->{date});

  my $from_dir = $from;
  my $to_dir = $to;
  $from_dir =~ s/\-/\//g;
  #$to_dir =~ s/\-/\//g;

  my $dir = "/opt/pos/common/data/execution_control/emails_send_monthly_z/$from_dir/$to_dir";
  print STDERR "\tdebug 1 - $from - $to - $dir\n";
  return if -d $dir;

  print STDERR "\tdebug 2 - $dir\n";

  my $tmp = $db->select(qq{
    SELECT id, login, used_for_training
    FROM clerks
    WHERE deleted = 0
    ORDER BY used_for_training DESC
  });

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

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

  print STDERR "\tdebug 3\n";

  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);

  sleep 60;

  #
  # send collected generated reports
  #

  my @files = ();

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

    push @files, {
      full_p => $File::Find::name,
      file => $_,
    };

  }, ( '/opt/pos/common/data/emails_to_send' ));

  foreach my $f (@files) {
    my( $y, $m, $d ) = ( "", "", "");

    if ($f->{file} =~ /^report_detailed_(\d\d\d\d)\-(\d\d)\-(\d\d)_/) {
      $y = $1;
      $m = $2;
      $d = $3;
    }
    elsif ($f->{file} =~ /^report_detailed_(\d\d\d\d)(\d\d)(\d\d)_/) {
      $y = $1;
      $m = $2;
      $d = $3;
    }

    next unless $y && $m && $d;

    my $date = "$y-$m-$d";

    eval {
      my $name = $STATION_NAME ? $STATION_NAME : $SAFT_BusinessName;

      my $stat = send_mail(
        to         => $INTERNET_SEND_MONTHLY_Z,
        subject    => "[$LANG] $SAFT_TaxRegistratioNumber / $name / $DOC_TYPE_SERIE / $from / $to",
        content    => "$LANG<br>=========<p>$SAFT_BusinessName<br><p>$f->{file}<br>",
        attachment => [ $f->{full_p} ],
      );

      if ($stat) {
        # mark this date as processed
        make_path($dir);
      }
    };

    unlink $f->{full_p};
  }

  print STDERR "\tdebug 4\n";
}

sub daily_z {
  my $db = shift;
  my $format = shift;

  print STDERR "daily_z()\n";

  print STDERR "\tdebug 0\n";

  my $dates = execution_dates($db, 'emails_send_daily_z');
  return unless scalar @$dates;

  print STDERR "\tdebug 1\n";

  my $tmp = $db->select(qq{
    SELECT id, login, used_for_training
    FROM clerks
    WHERE deleted = 0
    ORDER BY used_for_training DESC
  });

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

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

  print STDERR "\tdebug 2\n";

  foreach my $date (@$dates) {
    print STDERR "\t$date\n";

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

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

  print STDERR "\tdebug 3\n";

  sleep 30;

  #
  # send collected generated reports
  #

  my @files = ();

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

    push @files, {
      full_p => $File::Find::name,
      file => $_,
    };

  }, ( '/opt/pos/common/data/emails_to_send' ));

  foreach my $f (@files) {
    my( $y, $m, $d ) = ( "", "", "");

    if ($f->{file} =~ /^report_detailed_(\d\d\d\d)\-(\d\d)\-(\d\d)_/) {
      $y = $1;
      $m = $2;
      $d = $3;
    }
    elsif ($f->{file} =~ /^report_detailed_(\d\d\d\d)(\d\d)(\d\d)_/) {
      $y = $1;
      $m = $2;
      $d = $3;
    }

    next unless $y && $m && $d;

    my $date = "$y-$m-$d";

    eval {
      my $name = $STATION_NAME ? $STATION_NAME : $SAFT_BusinessName;

      my $stat = send_mail(
        to         => $INTERNET_SEND_DAILY_Z,
        subject    => "[$LANG] $SAFT_TaxRegistratioNumber / $name / $DOC_TYPE_SERIE / $date",
        content    => "$LANG<br>=========<p>$SAFT_BusinessName<br><p>$f->{file}<br>",
        attachment => [ $f->{full_p} ],
      );

      if ($stat) {
        # mark this date as processed
        execution_dates($db, 'emails_send_daily_z', $date);
      }
    };

    unlink $f->{full_p};
  }

  print STDERR "\tdebug 4\n";
}

sub dates_guess {
  my $date = shift;

  my( $y ) = $date =~ /^(\d\d\d\d)\-/;
  my( $m ) = $date =~ /^\d\d\d\d-(\d\d)\-/;

  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" )
}


