#!/usr/bin/perl

use strict;
use warnings;
use FindBin qw( $Bin );
use lib "$Bin/../../lib";
use Data::Dumper;
use Spreadsheet::WriteExcel;
use Encode qw( decode encode from_to );
use POSIX qw( strftime );
use Getopt::Long;

use App::POS::Config;
use App::POS::Machine::Station;
use App::POS::Machine::Server;
use App::POS::Utils qw( translate my_conv read_translation_file );

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

my $machine = undef;

if (exists $info->{STATION_NUMBER} && $info->{STATION_NUMBER} > 0) {
  $machine = App::POS::Machine::Station->new( config => $cfg );  
}
else {
  $machine = App::POS::Machine::Server->new( config => $cfg );  
}

#####################################################################
my $ENCODING = 'iso-8859-1';

my @TABLES = (
  { table => 'groups', name => &translate($machine, "FAMILIAS E SUBFAMILIAS") },
  { table => 'products', name => &translate($machine, "PRODUTOS") },
  { table => 'clerks', name => &translate($machine, "FUNCIONARIOS") },
  { table => 'customers', name => &translate($machine, "CLIENTES") },
  { table => 'product_menus', name => &translate($machine, "MENUS") },
  { table => 'product_names', name => &translate($machine, "TRADUCOES PRODUTOS") },
);

my %FIELDS = ();
read_translation_file($Bin."/../../etc/fields.txt", \%FIELDS);

my @MOBILE_MESSAGES = ();
read_translation_file($Bin."/../../etc/mobile_messages.txt", \@MOBILE_MESSAGES);

my @CONFIG_QUESTIONS = ();
read_translation_file($Bin."/../addons/machine_config/config_questions_server.txt", \@CONFIG_QUESTIONS);

my @CONFIG_QUESTIONS2 = ();
read_translation_file($Bin."/../addons/machine_config/config_questions_station.txt", \@CONFIG_QUESTIONS2);
#####################################################################

my $table_headers = undef;
my $table_headers_for_ui = undef;
my $dest_folder = undef;
my $dest_file_arg = undef;
my $config_questions = undef;
my $config_questions2 = undef;
my $messages = undef;
my $mobile_messages = undef;
my $tables_param = undef;
my $group_names = undef;

my $result = GetOptions(
  "config_questions"  => \$config_questions, # flag
  "messages"          => \$messages, # flag
  "config_questions2" => \$config_questions2, # flag
  "dest_folder=s"     => \$dest_folder,         # string
  "dest_file=s"       => \$dest_file_arg,         # string
  "mobile_messages"   => \$mobile_messages,
  "tables=s"          => \$tables_param,
  "group_names"       => \$group_names,
);

my %tables_only = ();

if (defined $tables_param) {
  my @t = split /,/, $tables_param;
  map { $tables_only{$_} = 1 } @t;

  if (exists $tables_only{products}) {
    $tables_only{product_names} = 1;
    $tables_only{product_menus} = 1;
  }
}

if (defined $mobile_messages) {
  my $str = "";

  foreach my $q (@MOBILE_MESSAGES) {
    my( $k, $v ) = each %{$q};

    if ($k =~ /^_/) {
      $k =~ s/^_//;
    }

    $v = $k unless $v;
    $str .= $k."=".&translate($machine, $v).'@';
  }
  
  $str =~ s/\@$//;

  print $str."\n";

  exit;
}
elsif (defined $config_questions2) {
  my $str = "";

  foreach my $q (@CONFIG_QUESTIONS2) {
    my( $k, $v ) = each %{$q};

    if ($k =~ /^_/) {
      $k =~ s/^_//;
    }

    $v = $k unless $v;
    $str .= $k."=".&translate($machine, $v).'@';
  }
  
  $str =~ s/\@$//;

  print $str."\n";

  exit;
}
elsif (defined $config_questions) {
  my $str = "";

  foreach my $q (@CONFIG_QUESTIONS) {
    my( $k, $v ) = each %{$q};

    if ($k =~ /^_/) {
      $k =~ s/^_//;
    }

    $v = $k unless $v;
    $str .= $k."=".&translate($machine, $v).'@';
  }
  
  $str =~ s/\@$//;

  print $str."\n";

  exit;
}
elsif (! defined $dest_folder) {
  die "Usage: $0 --dest_folder=<dest_folder> [--table_headers --config_questions --group_names]\n" unless defined $dest_folder;
}

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

my %deleted_products = ();
my $tmp_arr = $db->select("SELECT id FROM products WHERE deleted != 0");
map { $deleted_products{$_->{id}} = 1 } @$tmp_arr;

my $dest_file = "";

if (defined $dest_file_arg) {
  $dest_file = $dest_folder . "/" . $dest_file_arg;
}
else {
  $dest_file = $dest_folder . "/DB_" . &strftime("%Y%m%d_%H%M%S", localtime).".xls";
}

my $workbook  = Spreadsheet::WriteExcel->new($dest_file) or die "error: $!";

my $text = $workbook->add_format();
my $text_b = $workbook->add_format(); $text_b->set_bold();
my $numeric = $workbook->add_format(); $numeric->set_num_format('0.0000');
my $numeric_s = $workbook->add_format(); $numeric_s->set_num_format();

my %groups_info = ();
my $groups_tmp = $db->select("SELECT id, name, parent FROM groups WHERE deleted = 0");

foreach my $g (@$groups_tmp) {
  $groups_info{$g->{id}} = $g;
}

foreach my $t (@TABLES) {
  my $name = $t->{table};
  my $desc = $t->{name};

  my $table_name = $name;

  if (! exists $FIELDS{$name}) {
    die "Table $name don't have FIELDS defined...\n";
  }

  if (scalar keys %tables_only && ! exists $tables_only{$table_name}) {
    print "Ignoring table $table_name...\n";
    next;
  }

  my $worksheet = $workbook->add_worksheet(&my_conv($desc));

  my $c = 0;
  my $y = 0;

  # write headers
  foreach my $field (@{ $FIELDS{$name} }) {
    my( $fname, $fdesc ) = each %$field;
    $worksheet->write_string($c, $y++, &translate($machine, $fdesc), $text_b);
  }

  my @table_fields = $db->table_fields($name);
  my $has_deleted = 0;
  map { $has_deleted = 1 if $_->{attname} eq 'deleted' } @table_fields;

  my $rows;

  if ($table_fields[0]->{attname} eq 'id') {
    if ($has_deleted) {
      $rows = $db->select("SELECT * FROM $name WHERE deleted = 0 ORDER BY id");
    }
    else {
      $rows = $db->select("SELECT * FROM $name ORDER BY id");
    }
  }
  else {
    if ($has_deleted) {
      $rows = $db->select("SELECT * FROM $name WHERE deleted = 0");
    }
    else {
      $rows = $db->select("SELECT * FROM $name");
    }
  }

  $y = 0;

  # write content
  foreach my $row (@$rows) {
    # validate if product menus were deleted
    if ($table_name eq 'product_menus') {
      next if exists $deleted_products{$row->{product_id}};
      next if exists $deleted_products{$row->{product_menu_id}};
    }

    $c++;

    foreach my $field (@{ $FIELDS{$name} }) {
      my @k = keys %$field;
      next if $name eq 'products' && $k[0] eq 'groups';

      my $v = $row->{$k[0]};

      if ($name eq 'product_menus' && $k[0] eq 'step_number') {
        if ($v =~ /^\d+$/) {
          $v++;
        }
      }

      my $orig = $v;

      #eval { from_to( $v, "utf8", $ENCODING ) };
      #$v = $orig if $@;

      eval { encode("utf8", $v) };
      $v = $orig if $@;

      $worksheet->write_string($c, $y++, $v);
    }

    # get product's groups
    if ($name eq 'products') {
      my $groups = $db->select("SELECT group_id FROM product_groups WHERE product_id = ? ORDER BY group_id", $row->{id});
      my $groups_str = "";
      map { $groups_str .= $_->{group_id}."," } @$groups;

      if ($groups_str) {
        $groups_str =~ s/,$//;
        my @g = split /,/, $groups_str;

        my $fname = "";
        my $sfname = "";

        if (scalar @g == 1) {
          my $ginfo = $groups_info{$g[0]} || undef;

          if (defined $ginfo) {
            $sfname = $ginfo->{name};
            $fname = $groups_info{$ginfo->{parent}}->{name} || "";
          }
        }

        $worksheet->write_string($c, $y++, $groups_str);

        if ($fname && $sfname && defined $group_names) {
          $worksheet->write_string($c, $y++, $fname);
          $worksheet->write_string($c, $y++, $sfname);
        }
      }
    }

    $y = 0;
  }
}

system("sync");

sub _ {
  my $txt = shift;
  return $txt;
}

