#!/usr/bin/perl

use strict;
use warnings;
use FindBin qw( $Bin );
use lib "$Bin/../../lib";
use Data::Dumper;
use App::POS::Config;
use App::POS::Machine::Server;
use UUID::Tiny;
use File::Copy qw( copy );
use Number::Format;

my $NFORMATER = Number::Format->new();

my %DOCS_TO_HISTORY = (
  7  => 1, # fatura
  5  => 1, # fatura recibo
  8  => 1, # recibo
  12 => 1, # nota debito
  13 => 1, # nota credito
  14 => 1, # adiantamento
  32 => 1, # fatura fornecedor
  33 => 1, # # nota credito fornecedor
  34 => 1, # nota debito fornecedor
  35 => 1, # nota liquidacao fornecedor
);

my $DATE = shift;

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

my $machine = undef;

if (exists $info->{STATION_NUMBER} && $info->{STATION_NUMBER} == 0) {
  $machine = App::POS::Machine::Server->new( config => $cfg );  
} else {
  die "Needs to be executed in the server machine...\n";
}

my $machine_id=`/opt/pos/common/bin/machine_id`;
my $db = $machine->database();
my $dbh = $db->dbh();

my $recs = $db->select("SELECT id, gb_identifier FROM sales_headers WHERE fo_doc_number LIKE 'RE%'");
my %receipts = ();
map { $receipts{$_->{gb_identifier}} = $_->{id} } @$recs;

$recs = $db->select("SELECT dest_gb_identifier FROM document_operations");
my %used_receipts = ();
map { $used_receipts{$_->{dest_gb_identifier}} = 1 } @$recs;

foreach my $gbi (keys %receipts) {
  if (! exists $used_receipts{$gbi}) {
    my $doc_id = $receipts{$gbi};
    $recs = $db->select("SELECT key_value FROM sales_headers_aux WHERE key_name = 'docs_payed' AND header = $doc_id");
    my @docs = split /,/, $recs->[0]->{key_value};
    for (@docs) {
      my $val = $db->select("SELECT value FROM sales_headers WHERE gb_identifier = ?", $_);
      if (scalar @$val) {
        my $value = $val->[0]->{value};
        print STDERR "VOU INSERIR!!!\n";
        $db->do("INSERT INTO document_operations VALUES (?, ?, ?)", $_, $gbi, $value);
      }
    }
  }
}

my $doc_type_str = join(",", keys %DOCS_TO_HISTORY);
$doc_type_str =~ s/,$//;

$db->do("DELETE FROM document_history");

my $sth = $db->dbh()->prepare(qq{
  SELECT *
  FROM sales_headers
  WHERE doc_type IN ($doc_type_str)
  ORDER BY id ASC
});

$sth->execute();

while (my $h = $sth->fetchrow_hashref) {
  my $amount_payed = 0;
  my $doc_value = $h->{value};
  $doc_value *= -1 if $h->{doc_type} == 8 || $h->{doc_type} == 35;

  if ($h->{doc_type} == 8 || $h->{doc_type} == 35) {
    my $docs_payed = $db->select("SELECT * FROM document_operations WHERE dest_gb_identifier = ?", $h->{gb_identifier});

    #print Dumper($docs_payed);
    #exit;

    foreach my $doc (@$docs_payed) {
      my $v = $doc->{value}*1;

      $db->do(qq{
        UPDATE document_history
        SET amount_payed = amount_payed + $v
        WHERE gbi = ? AND doc_type <> 5
      }, $doc->{source_gb_identifier});
    }
  }
  elsif ($h->{doc_type} == 5 || $h->{doc_type} == 31) {
    $amount_payed = $doc_value;
  }

  my $id = $db->next_id("document_history");
  print STDERR "header: ".sprintf("%6s", $id).", business_date: ".$h->{business_date}.", fo_doc_number: ".$h->{fo_doc_number}."\n";

  $db->do(qq{
    INSERT INTO document_history VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
  }, $id, $h->{id}, $h->{gb_identifier}, $h->{customer_nif}, $h->{business_date}, $h->{doc_type}, $h->{fo_doc_number}, _my_round($doc_value), _my_round($amount_payed));
}

$recs = $db->select("SELECT header FROM sales_headers_aux WHERE key_name = 'invoice_is_payed' AND key_value = '1'");

for (@$recs) {
  $db->do("UPDATE document_history SET amount_payed = doc_value WHERE header = ?", $_->{header});
}

if (defined $DATE) {
  my $docs = $db->select(qq{
    SELECT MIN(doc_date) AS doc_date, nif
    FROM document_history
    WHERE doc_type <> 8 AND doc_type <> 35
    GROUP BY doc_date, nif
  });

  for (@$docs) {
    $db->do("DELETE FROM document_history WHERE nif = ? AND (doc_type = ? OR doc_type = ?)", $_->{nif}, 8, 35);
    $db->do("DELETE FROM document_history WHERE nif = ? AND doc_date < '".$DATE."'", $_->{nif});
    $db->do("UPDATE document_history SET amount_payed = 0 WHERE doc_type <> 5 AND doc_type <> 31");
  }

  print STDERR "CLEAN ALL BEFORE: $DATE...\n";

  exit;
}

sub _my_round {
  my $d = shift;
  return sprintf("%.2f", $NFORMATER->round($d, 2));
}
