#!/usr/bin/perl

use strict;
use warnings;
use FindBin qw( $Bin );
use File::Copy qw( move copy );
use File::Path qw( make_path remove_tree );
use lib "$Bin/../../lib";
use POSIX qw( strftime );
use Data::Dumper;
use Date::Calc qw( Days_in_Month Add_Delta_Days Date_to_Days );
use JSON::XS;
use File::Slurp qw( write_file );
use DBI;
use File::Find qw( find );

use App::POS::Config;
use App::POS::Utils qw(
  send_mail execution_dates emails_validate random_sleep ftp_put
  file_modif_secs send_alert_to_ui
);
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 $APP;

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

if (-e "/opt/pos/common/addons/saft-pt/app.1.07") {
  $APP = "/opt/pos/common/addons/saft-pt/app.1.07";
}
elsif (-e "/opt/pos/common/addons/saft-pt/app.1.06") {
  $APP = "/opt/pos/common/addons/saft-pt/app.1.06";
}
elsif (-e "/opt/pos/common/addons/saft-pt/app.1.05") {
  $APP = "/opt/pos/common/addons/saft-pt/app.1.05";
}
elsif (-e "/opt/pos/common/addons/saft-pt/app.1.04") {
  $APP = "/opt/pos/common/addons/saft-pt/app.1.04";
}
elsif (-e "/opt/pos/common/addons/saft-pt/app.1.03") {
  $APP = "/opt/pos/common/addons/saft-pt/app.1.03";
}

if ($server->is_arm()) {
  if (-e "/opt/pos/common/addons/saft-pt/app.gb3") {
    $APP = "/opt/pos/common/addons/saft-pt/app.gb3"
  } elsif (-e "/opt/pos/common/addons/saft-pt/app.arm") {
    $APP = "/opt/pos/common/addons/saft-pt/app.arm";
  }
}

die "Can't find saft exporter...\n" unless $APP;

my $db = $server->database();

my $LANG = $info->{LANG} || "";
my $DOC_TYPE_SERIE = $info->{DOC_TYPE_SERIE} || "";
my $STATION_NUMBER = $info->{STATION_NUMBER} || 0;
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 $SAFT_ZipXml = $info->{SAFT_ZipXml} || 0;
my $GENERATE_LOCALY = $info->{SAFT_GENERATE_LOCALY} || "";
my $INTERNET_SEND_DAILY_SAFT = $info->{INTERNET_SEND_DAILY_SAFT} || "";
my $INTERNET_SEND_MAIL_HARDLOCK = $info->{INTERNET_SEND_MAIL_HARDLOCK} || "";

my $SAFT_GENERATE_LOCALY_FTP_SERVER = $info->{SAFT_GENERATE_LOCALY_FTP_SERVER} // "";
my $SAFT_GENERATE_LOCALY_FTP_PORT = $info->{SAFT_GENERATE_LOCALY_FTP_PORT} // "";
my $SAFT_GENERATE_LOCALY_FTP_USER = $info->{SAFT_GENERATE_LOCALY_FTP_USER} // "";
my $SAFT_GENERATE_LOCALY_FTP_PASS = $info->{SAFT_GENERATE_LOCALY_FTP_PASS} // "";
my $SAFT_GENERATE_LOCALY_FTP_FOLDER = $info->{SAFT_GENERATE_LOCALY_FTP_FOLDER} // "";

#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/.saft_daily.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 ($GENERATE_LOCALY) {
  saft_daily_local_folder($db, $GENERATE_LOCALY);
}

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

  saft_daily_network($db);
}

unlink $control_file;


#
# Functions
#

sub saft_daily_local_folder {
  my( $db, $folder ) = @_;

  print STDERR "saft_daily_local_folder - $folder\n";

  make_path($folder) unless -d $folder;

  my $dates = execution_dates($db, 'saft_daily_local_folder');

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

    # creating this file will make saft file to allways be ziped
    write_file("/tmp/.zip_saft_file", 1);

    system("$APP $folder $date $date");

    my $exists = `ls $folder/*#$date#$date#* 2> /dev/null | head -1`;

    # file was generated, mark this date as done
    if ($exists) {
      chop($exists);

      my $file_to_send = $exists;
      my $old_file_to_send = $file_to_send;
      my $biz_name = $SAFT_BusinessName;
      $biz_name =~ tr/ %-*\/,/______/;
      $file_to_send =~ s/\.xml$//;
      $file_to_send =~ s/\.xml\.zip$//;
      $file_to_send = $file_to_send."#$biz_name.xml";
      #$file_to_send = "$file_to_send.zip" if $SAFT_ZipXml;
      $file_to_send = "$file_to_send.zip";
      $file_to_send =~ tr/ /_/;

      move($exists, $file_to_send);

      execution_dates($db, 'saft_daily_local_folder', $date);

    }
  }

  # put saft files in ftp
  if (
    $SAFT_GENERATE_LOCALY_FTP_SERVER &&
    $SAFT_GENERATE_LOCALY_FTP_PORT &&
    $SAFT_GENERATE_LOCALY_FTP_USER &&
    $SAFT_GENERATE_LOCALY_FTP_PASS &&
    $SAFT_GENERATE_LOCALY_FTP_FOLDER
  ) {
    my $ftp_server = $SAFT_GENERATE_LOCALY_FTP_SERVER;
    my $ftp_port = $SAFT_GENERATE_LOCALY_FTP_PORT;
    my $ftp_login = $SAFT_GENERATE_LOCALY_FTP_USER;
    my $ftp_pass = $SAFT_GENERATE_LOCALY_FTP_PASS;
    my $ftp_folder = $SAFT_GENERATE_LOCALY_FTP_FOLDER;

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

      my $st = 0;

      eval {
        $st = ftp_put($ftp_server, $ftp_port, $ftp_login, $ftp_pass, $ftp_folder, $File::Find::name);
      };

      if ($@) {
        print STDERR "ftp error - $@\n";
        return;
      }

      if ($st) {
        unlink $File::Find::name;
      }
    }, ( $folder ));
  }

}

sub saft_daily_network {
  my $db = shift;

  print STDERR "saft_daily_network\n";

  # check network connection
  my $has_network = `/opt/pos/common/bin/has_network`;

  if ($has_network !~ /YES/i) {
    print STDERR "\tNo network connection...\n";
    return;
  }

  my $dates = execution_dates($db, 'saft_daily_network');

  my $folder = "/tmp/saft_to_network";
  make_path($folder) unless -d $folder;

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

    # creating this file will make saft file to allways be ziped
    write_file("/tmp/.zip_saft_file", 1);

    system("$APP $folder $date $date");

    my $exists = `ls $folder/*#$date#$date#* 2> /dev/null | head -1`;

    # file was generated, send by email and mark this date as done
    if ($exists) {
      chop($exists);

      my $file_to_send = $exists;
      my $old_file_to_send = $file_to_send;
      my $biz_name = $SAFT_BusinessName;
      $biz_name =~ tr/ %-*\/,/______/;
      $file_to_send =~ s/\.xml$//;
      $file_to_send =~ s/\.xml\.zip$//;
      $file_to_send = $file_to_send."#$biz_name.xml";
      #$file_to_send = "$file_to_send.zip" if $SAFT_ZipXml;
      $file_to_send = "$file_to_send.zip";
      $file_to_send =~ tr/ /_/;

      move($exists, $file_to_send);

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

        my $stat = send_mail(
          to         => $INTERNET_SEND_DAILY_SAFT,
          subject    => "[$LANG SAF-T DAILY] $SAFT_TaxRegistratioNumber / $name / $date",
          content    => "$LANG<br>====<p>$SAFT_BusinessName<p>SAF-T $date<p>$SAFT_TaxRegistratioNumber<br>",
          attachment => [ $file_to_send ],
        );

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

      unlink $file_to_send;
    }
  }

  remove_tree($folder);
}

