package App::POS::API::Api;

use Mojo::Base 'Mojolicious::Controller';
#use Mojo::JSON qw( encode_json decode_json );
#use Mojo::UserAgent;
use Data::Dumper;
use Digest::MD5 qw( md5_hex );
#use Time::ParseDate;
#use Date::Parse;
use POSIX qw( strftime );
use Encode qw( encode decode );
use File::Slurp qw( read_dir read_file write_file );
use File::Copy qw( move copy );
use Time::HiRes qw( sleep );

use App::POS::Check;
use App::POS::Utils qw(
  tables_refresh date_based_on_closing_hour my_conv fix_encoding
);

sub route_to {
  my $s = shift;
  my $route_to = $s->param('route_to');
  my $can = $s->can($route_to);
  $can ||= 0;

  if (! $can) {
    $s->render(json => {
      error => ref($s)." controller don't have action - $route_to"
    });
  }
  else {
    $s->$route_to();
  }
}

# curl -X GET "http://localhost:3041/api/needs_sync"
sub sync_md5 {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->params->to_hash;
  #my $p = $req->json;

  my $recs = $db->select("SELECT MAX(modified) AS max FROM products WHERE deleted = 0");
  my $modif_products = scalar @$recs ? $recs->[0]->{max} : '';

  $recs = $db->select("SELECT MAX(modified) AS max FROM groups WHERE deleted = 0");
  my $modif_groups = scalar @$recs ? $recs->[0]->{max} : '';

  my $md5 = md5_hex($modif_products . "#" . $modif_groups);

  return $s->json({ md5 => $md5 });
}

# curl -X GET "http://localhost:3041/api/license_info"
sub license_info {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $p = $req->params->to_hash;
  #my $p = $req->json;

  my $hardlock = "";

  if (-e "/opt/pos/.hardlock") {
    my $tmp = read_file("/opt/pos/.hardlock");
    $tmp ||= "";
    $tmp =~ s/\n//g;
    $tmp =~ s/\r//g;

    if ($tmp && -e $tmp) {
      $tmp = read_file($tmp);
      $tmp =~ s/\n//g;
      $tmp =~ s/\r//g;
      return $s->json({ license => $tmp });
    }
  }

  return $s->json({ license => '' });
}

# curl -X GET "http://localhost:3041/api/areas"
sub areas {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $p = $req->params->to_hash;
  #my $p = $req->json;

  my $info = $s->pos_config_loaded();

  my @areas = ();

  foreach my $a (@{$info->{AREA}}) {
    my @arr = split /,/, $a;
    push @areas, \@arr;
  }

  return $s->json({ areas => \@areas });
}

# curl -X GET "http://localhost:3041/api/areas_friendly"
sub areas_friendly {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  my $machine = $s->machine();

  my $areas = $machine->areas();
  my @recs = ();

  foreach my $a (@$areas) {
    next unless $a->number() =~ /^\d+$/;

    push @recs, {
      number => $a->number(),
      name => $a->name(),
      tables_number => $a->tables_number(),
      start_table => $a->start_table(),
      price_field => $a->price_field(),
      vat_field => $a->vat_field(),
      prices_wo_vat => $a->prices_wo_vat(),
    };
  }

  return $s->json(\@recs);
}

# curl -X GET "http://localhost:3041/api/checks?area=0"
sub checks {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $p = $req->params->to_hash;
  #my $p = $req->json;

  $p->{area} //= "";

  if ($p->{area} eq '') {
    return $s->json({ error => 'missing area parameter...' });
  }

  my $dir = "/opt/pos/server/data/areas/$p->{area}";

  if (! -d $dir) {
    return $s->json({ error => 'invalid area...' });
  }

  my @files = <$dir/*.total>;
  my @checks = ();

  foreach my $f (@files) {
    next unless $f =~ /\/(\d+)\.total$/;

    my $num = $1;
    my $total = read_file($f);
    $total =~ s/\n|\r//g;

    push @checks, {
      number => $num*1,
      total => $total*1 || 0,
      locked => -e "$dir/$num.lock" ? 1 : 0,
    };
  }

  @checks = sort { $a->{number} <=> $b->{number} } @checks;

  return $s->json({ checks => \@checks });
}

# curl -X GET "http://localhost:3041/api/check_get?area=0&number=1"
sub check_get {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $p = $req->params->to_hash;
  #my $p = $req->json;

  $p->{area} //= "";
  $p->{number} //= "";

  if ($p->{area} eq '' || $p->{number} eq '') {
    return $s->json({ error => 'missing area  or number parameter...' });
  }

  my $f = "/opt/pos/server/data/areas/$p->{area}/$p->{number}";

  if (! -e $f) {
    return $s->json({ error => 'invalid check...' });
  }

  my $db = $s->db();

  my $o = App::POS::Check->new( file => $f );
  my $check = $o->data();

  my %product_ids = ();

  foreach my $d (@{$check->{details}}) {
    $product_ids{$d->[1]} = 1;
  }

  my $ids = join(",", keys %product_ids);

  my $prods = $db->select("SELECT id, name FROM products WHERE id IN ($ids)");

  foreach my $p (@$prods) {
    $check->{product_names}->{$p->{id}} = $p->{name};
  }

  return $s->json({ check => $check });
}

# curl -X GET "http://localhost:3041/api/customer_by_nif?nif=507281420"
sub customer_by_nif {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $p = $req->params->to_hash;
  #my $p = $req->json;

  $p->{nif} //= "";

  if ($p->{nif} eq '') {
    return $s->json({ error => 'missing nif parameter...' });
  }

  my $db = $s->db();

  my $c = $db->select(
    "SELECT * FROM customers WHERE nif = ? AND deleted = 0",
    $p->{nif},
  );

  return $s->json({ error => 'NIF not found...' }) unless scalar @$c;
  return $s->json({ customer => $c->[0] });
}

# curl -X GET "http://localhost:3041/api/check_update?area=0&number=1&customer_nif=507281420&customer_name=Uloan&bill_is_out=0"
sub check_update {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $p = $req->params->to_hash;
  #my $p = $req->json;

  $p->{area} //= "";
  $p->{number} //= "";
  $p->{customer_nif} //= "";
  $p->{customer_name} //= "";
  $p->{bill_is_out} ||= 0;

  if ($p->{area} eq '' || $p->{number} eq '') {
    return $s->json({ error => 'missing area  or number parameter...' });
  }

  my $f = "/opt/pos/server/data/areas/$p->{area}/$p->{number}";

  if (! -e $f) {
    return $s->json({ error => 'invalid check...' });
  }

  my $f_lock = "/opt/pos/server/data/areas/$p->{area}/$p->{number}.lock";

  if (-e $f_lock) {
    return $s->json({ error => 'check locked...' });
  }

  if ($p->{customer_nif}) {
    $p->{customer_nif} =~ s/#//g;
    $p->{customer_nif} =~ s/'//g;
  }

  my $db = $s->db();

  my $customer = $db->select(
    "SELECT * FROM customers WHERE nif = ? AND deleted = 0",
    $p->{customer_nif},
  );

  my $customer_id = scalar @$customer ? $customer->[0]->{id} : "";

  my @lines = read_file($f);
  my $headers_started = 0;

  my @lines_final = ();

  foreach my $l (@lines) {
    $l =~ s/\n|\r//g;
    next if $l eq '';

    if ($l eq 'HEADER') {
      push @lines_final, $l;
      $headers_started = 1;
    }
    else {
      if ($l eq 'DETAILS') {
        push @lines_final, $l;
        $headers_started = 0;
      }
      else {
        if ($headers_started) {
          my @a = split /#/, $l;
          $a[11] = $customer_id;
          $a[12] = encode("utf8", $p->{customer_name});
          $a[13] = $p->{customer_nif};
          my $str = join("#", @a);
          push @lines_final, $str;
        }
        else {
          push @lines_final, $l;
        }
      }
    }
  }

  my $cnt = join("\n", @lines_final);
  write_file("/tmp/check.$$.txt", $cnt);
  move("/tmp/check.$$.txt", $f);

  if ($p->{bill_is_out}) {
    write_file("$f.bill", localtime(time) . "\n");
    tables_refresh();
  }

  return $s->json({ success => 1 });
}

# curl -X POST "http://localhost:3041/api/clerks" -H "Content-Type: application/json"
# curl -X POST "http://localhost:3041/api/clerks" -H "Content-Type: application/json" -d '{"id":"5"}'
sub clerks {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{id} ||= "";

  my $sql_aux = "";
  my @params = ();

  if ($p->{id}) {
    $sql_aux .= " AND id = ?";
    push @params, $p->{id};
  }

  my $recs = $db->select(qq{
    SELECT *
    FROM clerks
    WHERE deleted = 0 AND blocked_stations NOT LIKE '%99%' AND
      login <> '' AND login <> '--' $sql_aux
    ORDER BY login
  }, @params);

  return $s->json($recs)
}

# curl -X POST "http://localhost:3041/api/customers" -H "Content-Type: application/json"
# curl -X POST "http://localhost:3041/api/customers" -H "Content-Type: application/json" -d '{"id":"5"}'
sub customers {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{id} ||= "";

  my $sql_aux = "";
  my @params = ();

  if ($p->{id}) {
    $sql_aux .= " AND id = ?";
    push @params, $p->{id};
  }

  my $recs = $db->select(qq{
    SELECT *
    FROM customers
    WHERE deleted = 0 $sql_aux
    ORDER BY name
  }, @params);

  return $s->json($recs)
}

# curl -X POST "http://localhost:3041/api/products_tree" -H "Content-Type: application/json"
# curl -X POST "http://localhost:3041/api/products_tree" -H "Content-Type: application/json" -d '{"id":"5"}'
sub products_tree {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{id} ||= "";

  my $sql_aux = "";
  my @params = ();

  if ($p->{id}) {
    $sql_aux .= " AND p.id = ?";
    push @params, $p->{id};
  }

  my $products_extra_data = _get_products_extra_data($db);

  my $recs = $db->select(qq{
    SELECT sf.name AS sub_name, sf.id AS sub_id, f.id AS top_id, f.name AS top_name,
      f.button_bg_color AS top_bg_color, f.button_color AS top_color,
      sf.button_color AS sub_color, sf.button_bg_color AS sub_bg_color,
      sf.priority AS sub_priority, f.priority AS top_priority, p.id, p.name,
      p.sell_vat1, p.sell_vat2, p.sell_price1, p.sell_price2, p.sell_price3,
      p.sell_price4, p.sell_price5, p.sell_price_menu, p.is_message, p.is_extra,
      p.barcode, p.handy_plu, p.is_menu, p.is_weight, p.ask_price, p.which_extras,
      p.button_color AS color, p.button_bg_color AS bg_color, p.stock_use,
      p.stock_min, p.stock_current, p.button_text, p.parent_product
    FROM product_groups pg
    LEFT JOIN products p ON (pg.product_id = p.id)
    LEFT JOIN groups sf ON (pg.group_id = sf.id)
    LEFT JOIN groups f ON (sf.parent = f.id)
    WHERE p.deleted = 0 AND f.deleted = 0 AND sf.deleted = 0 AND
      p.name <> '' AND f.name <> '' AND sf.name <> '' AND
      p.name <> '--' AND f.name <> '--' AND sf.name <> '--' $sql_aux
    ORDER BY f.priority DESC, f.name, sf.priority DESC, sf.name, p.priority DESC, p.name
  }, @params);

  my %groups = ();
  my %did = ();
  my $idx = 0;

  my $groups_img_dir = $s->machine->server_dir_data() . "/group_images";
  my $products_img_dir = $s->machine->server_dir_data() . "/product_images";

  foreach my $r (@$recs) {
    if (exists $did{ $r->{sub_id}."#".$r->{top_id}."#".$r->{id} }) {
      next;
    }

    $did{ $r->{sub_id}."#".$r->{top_id}."#".$r->{id} } = 1;

    if (! exists $groups{$r->{top_id}}) {
      $groups{$r->{top_id}}->{priority} = $r->{top_priority};
      $groups{$r->{top_id}}->{id} = $r->{top_id};
      $groups{$r->{top_id}}->{name} = $r->{top_name};
      $groups{$r->{top_id}}->{bg_color} = $r->{top_bg_color} ? sprintf("#%06x", $r->{top_bg_color}) : '';
      $groups{$r->{top_id}}->{color} = $r->{top_color} ? sprintf("#%06x", $r->{top_color}) : '';
      $groups{$r->{top_id}}->{idx} = $idx;

      if (-e "$groups_img_dir/$r->{top_id}.png") {
        $groups{$r->{top_id}}->{image} = "$r->{top_id}.png";
        $groups{$r->{top_id}}->{image_url} = "/api/image?dir=group_images&file=$r->{top_id}.png";
      } else {
        $groups{$r->{top_id}}->{image} = "";
        $groups{$r->{top_id}}->{image_url} = "";
      }
    }

    if (! exists $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}) {
      $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{priority} = $r->{sub_priority};
      $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{id} = $r->{sub_id};
      $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{name} = $r->{sub_name};
      $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{bg_color} = $r->{sub_bg_color} ? sprintf("#%06x", $r->{sub_bg_color}) : '';
      $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{color} = $r->{sub_color} ? sprintf("#%06x", $r->{sub_color}) : '';
      $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{idx} = $idx;

      if (-e "$groups_img_dir/$r->{top_id}.png") {
        $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{image} = "$r->{sub_id}.png";
        $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{image_url} = "/api/image?dir=group_images&file=$r>{sub_id}.png";
      } else {
        $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{image} = "";
        $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{image_url} = "";
      }
    }

    $r->{which_extras} ||= "";
    $r->{bg_color} ||= "";
    $r->{color} ||= "";
    $r->{sub_fam_bg_color} ||= "";
    $r->{sub_fam_color} ||= "";
    $r->{fam_bg_color} ||= "";
    $r->{fam_color} ||= "";
    $r->{stock_current} ||= 0;
    $r->{stock_use} ||= 0;
    $r->{stock_min} ||= 0;
    $r->{barcode} ||= "";
    $r->{button_text} ||= "";

    push @{$groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{products}}, {
      idx => $idx,
      id => $r->{id},
      products_extra_data => exists $products_extra_data->{$r->{id}} ? $products_extra_data->{$r->{id}} : {},
      name => $r->{name},
      button_text => $r->{button_text},
      sell_vat1 => $r->{sell_vat1}*1,
      sell_vat2 => $r->{sell_vat2}*1,
      sell_price1 => $r->{sell_price1}*1,
      sell_price2 => $r->{sell_price2}*1,
      sell_price3 => $r->{sell_price3}*1,
      sell_price4 => $r->{sell_price4}*1,
      sell_price5 => $r->{sell_price5}*1,
      sell_price_menu => $r->{sell_price_menu}*1,
      is_menu => $r->{is_menu},
      is_message => $r->{is_message},
      is_extra => $r->{is_extra},
      barcode => $r->{barcode},
      handy_plu => $r->{handy_plu}*1 || '',
      is_weight => $r->{is_weight},
      ask_price => $r->{ask_price},
      which_extras => $r->{which_extras},
      color => $r->{color} ? sprintf("#%06x", $r->{color}) : '',
      bg_color => $r->{bg_color} ? sprintf("#%06x", $r->{bg_color}) : '',
      stock_use => $r->{stock_use},
      stock_min => $r->{stock_min},
      stock_current => $r->{stock_current},
    };

    $groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{total_products} = scalar @{$groups{$r->{top_id}}->{subfamilies}->{$r->{sub_id}}->{products}};

    $idx++;
  }

  return $s->json(\%groups);
}

# curl -X POST "http://localhost:3041/api/products" -H "Content-Type: application/json"
# curl -X POST "http://localhost:3041/api/products" -H "Content-Type: application/json" -d '{"id":"5"}'
# curl -X POST "http://localhost:3041/api/products" -H "Content-Type: application/json" -d '{"barcode":"1234567890123"}'
# curl -X POST "http://localhost:3041/api/products" -H "Content-Type: application/json" -d '{"handy_plu":"10"}'
sub products {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{id} ||= "";
  $p->{barcode} ||= "";
  $p->{fam_id} ||= "";
  $p->{sub_fam_id} ||= "";
  $p->{barcode} ||= "";
  $p->{handy_plu} ||= "";
  $p->{extra_data_fields} ||= "";
  $p->{extra_data_values} ||= "";
  $p->{product_extra_data} ||= {};

  my %ed_fields = ();
  my %ed_values = ();

  if ($p->{extra_data_fields}) {
    my @fields = split /,/, $p->{extra_data_fields};
    my @values = split /,/, $p->{extra_data_values};

    if (scalar @fields == scalar @values) {
      for (my $i=0; $i < scalar @fields; $i++) {
        $ed_fields{$fields[$i]} = $i;
      }

      for (my $i=0; $i < scalar @values; $i++) {
        $ed_values{$i} = $values[$i];
      }
    }
  }

  my $sql_aux = "";
  my @params = ();

  if ($p->{id}) {
    $sql_aux .= " AND p.id = ?";
    push @params, $p->{id};
  }

  if ($p->{barcode}) {
    my $bc = uc($p->{barcode});
    $sql_aux .= " AND UPPER(p.barcode) LIKE '%$bc%'";
  }

  if ($p->{handy_plu}) {
    $sql_aux .= " AND p.handy_plu = ?";
    push @params, $p->{handy_plu};
  }

  if ($p->{fam_id}) {
    $sql_aux .= " AND f.id = ?";
    push @params, $p->{fam_id};
  }

  if ($p->{sub_fam_id}) {
    $sql_aux .= " AND sf.id = ?";
    push @params, $p->{sub_fam_id};
  }

  my $products_extra_data = _get_products_extra_data($db);

  my $q = qq{
    SELECT sf.name AS sub_fam_name, sf.id AS sub_fam_id, f.id AS fam_id, f.name AS fam_name,
      f.button_bg_color AS fam_bg_color, f.button_color AS fam_color,
      sf.button_color AS sub_fam_color, sf.button_bg_color AS sub_fam_bg_color,
      sf.priority AS sub_fam_priority, f.priority AS fam_priority, p.id, p.name,
      p.sell_vat1, p.sell_vat2, p.sell_price1, p.sell_price2, p.sell_price3,
      p.sell_price4, p.sell_price5, p.sell_price_menu, p.is_message, p.is_extra,
      p.barcode, p.handy_plu, p.is_menu, p.is_weight, p.ask_price, p.which_extras,
      p.button_color AS color, p.button_bg_color AS bg_color, p.stock_use,
      p.stock_min, p.stock_current, p.button_text, p.parent_product
    FROM product_groups pg
    LEFT JOIN products p ON (pg.product_id = p.id)
    LEFT JOIN groups sf ON (pg.group_id = sf.id)
    LEFT JOIN groups f ON (sf.parent = f.id)
    WHERE p.deleted = 0 AND f.deleted = 0 AND sf.deleted = 0 AND
      p.name <> '' AND f.name <> '' AND sf.name <> '' AND
      p.name <> '--' AND f.name <> '--' AND sf.name <> '--' $sql_aux
    ORDER BY f.priority DESC, f.name, sf.priority DESC, sf.name, p.priority DESC, p.name
  };

  #print STDERR Dumper($p);
  #print STDERR "## $q\n";
  #print STDERR Dumper(\@params);

  my $recs = $db->select($q, @params);

  my $groups_img_dir = $s->machine->server_dir_data() . "/group_images";
  my $products_img_dir = $s->machine->server_dir_data() . "/product_images";

  my @final = ();

  for (@$recs) {
    $_->{product_extra_data} = exists $products_extra_data->{$_->{id}} ? $products_extra_data->{$_->{id}} : {};

    # we're filtering by product extra data
    if ($p->{product_extra_data}) {
      my $valid_extra_data = 1;

      if (scalar keys %{$p->{product_extra_data}}) {
        while (my ($k, $v) = each %{$p->{product_extra_data}}) {
          if (! exists $_->{product_extra_data}->{$k} || $_->{product_extra_data}->{$k} ne $p->{product_extra_data}->{$k}) {
            $valid_extra_data = 0;
          }
        }
      }

      next unless $valid_extra_data;
    }

    $_->{which_extras} ||= "";
    $_->{bg_color} ||= "";
    $_->{color} ||= "";
    $_->{sub_fam_bg_color} ||= "";
    $_->{sub_fam_color} ||= "";
    $_->{fam_bg_color} ||= "";
    $_->{fam_color} ||= "";
    $_->{stock_current} ||= 0;
    $_->{stock_use} ||= 0;
    $_->{stock_min} ||= 0;
    $_->{barcode} ||= "";
    $_->{button_text} ||= "";

    if (-e "$groups_img_dir/$_->{fam_id}.png") {
      $_->{fam_image} = "$_->{fam_id}.png";
      $_->{fam_image_url} = "/api/image?dir=group_images&file=$_->{fam_id}.png";
    } else {
      $_->{fam_image} = "";
      $_->{fam_image_url} = "";
    }

    if (-e "$groups_img_dir/$_->{fam_id}.png") {
      $_->{fam_image} = "$_->{fam_id}.png";
      $_->{fam_image_url} = "/api/image?dir=group_images&file=$_->{fam_id}.png";
    } else {
      $_->{fam_image} = "";
      $_->{fam_image_url} = "";
    }

    if (-e "$groups_img_dir/$_->{sub_fam_id}.png") {
      $_->{sub_fam_image} = "$_->{sub_fam_id}.png";
      $_->{sub_fam_image_url} = "/api/image?dir=group_images&file=$_->{sub_fam_id}.png";
    } else {
      $_->{sub_fam_image} = "";
      $_->{sub_fam_image_url} = "";
    }

    if (-e "$products_img_dir/$_->{id}.png") {
      $_->{image} = "$_->{id}.png";
      $_->{image_url} = "/api/image?dir=product_images&file=$_->{id}.png";
    } else {
      $_->{image} = "";
      $_->{image_url} = "";
    }

    # lets try to filter products extra data
    if (scalar keys %ed_fields) {
      foreach my $field_name (keys %ed_fields) {
        my $field_idx = $ed_fields{$field_name};
        my $field_value = $ed_values{$field_idx};

        if (exists $_->{product_extra_data}->{$field_name} && $_->{product_extra_data}->{$field_name} eq $field_value) {
          push @final, $_;
        }
      }
    }
    else {
      push @final, $_;
    }
  }

  return $s->json(\@final);
}

# curl -X GET "http://localhost:3041/api/products_extra_data"
# curl -X GET "http://localhost:3041/api/products_extra_data?field_name=drive
# curl -X GET "http://localhost:3041/api/products_extra_data?field_name=drive&field_value=1"
sub products_extra_data {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  #my $p = $req->json;
  my $p = $req->params->to_hash;

  $p->{field_name} ||= "";
  $p->{field_value} //= "";

  my @params = ();
  my $sql_aux = "";

  if ($p->{field_name}) {
    $sql_aux .= " AND field_name = ?";
    push @params, $p->{field_name};
  }

  if ($p->{field_value} ne '') {
    $sql_aux .= " AND field_value = ?";
    push @params, $p->{field_value};
  }

  my $q = qq{
    SELECT p.id, p.name AS product_name, ped.field_name, ped.field_value,
      p.button_text
    FROM products_extra_data ped
    LEFT JOIN products p ON (ped.product_id = p.id)
    WHERE p.deleted = 0 $sql_aux
  };

  my $recs = $db->select($q, @params);

  return $s->json($recs);
}

# curl -X GET "http://localhost:3041/api/groups"
sub groups {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  my $recs = $db->select(qq{
    SELECT f.id AS fam_id, f.name AS fam_name,
      f.button_bg_color AS fam_bg_color, f.button_color AS fam_color
    FROM groups f
    WHERE f.deleted = 0 AND f.parent = 0 AND name <> '' AND name <> '--'
    ORDER BY f.priority DESC, f.name
  });

  my $img_dir = $s->machine->server_dir_data() . "/group_images";

  for (@$recs) {
    if (-e "$img_dir/$_->{fam_id}.png") {
      $_->{fam_image} = "$_->{fam_id}.png";
      $_->{fam_image_url} = "/api/image?dir=group_images&file=$_->{fam_id}.png";
    } else {
      $_->{fam_image} = "";
      $_->{fam_image_url} = "";
    }
  }

  return $s->json($recs);
}

# curl -X GET "http://localhost:3041/api/departments"
sub departments {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  my $recs = $db->select(qq{
    SELECT sf.name AS sub_fam_name, sf.id AS sub_fam_id, f.id AS fam_id,
      f.name AS fam_name, f.button_bg_color AS fam_bg_color,
      f.button_color AS fam_color, sf.button_color AS sub_fam_color,
      sf.button_bg_color AS sub_fam_bg_color, sf.priority AS sub_fam_priority,
      f.priority AS fam_priority
    FROM groups sf
    LEFT JOIN groups f ON (sf.parent = f.id)
    WHERE f.deleted = 0 AND sf.deleted = 0 AND sf.parent <> 0 AND sf.name <> '' AND
      f.name <> '' AND sf.name <> '--' AND f.name <> '--'
    ORDER BY f.priority DESC, f.name, sf.priority DESC, sf.name
  });

  my $img_dir = $s->machine->server_dir_data() . "/group_images";

  for (@$recs) {
    if (-e "$img_dir/$_->{fam_id}.png") {
      $_->{fam_image} = "$_->{fam_id}.png";
      $_->{fam_image_url} = "/api/image?dir=group_images&file=$_->{fam_id}.png";
    } else {
      $_->{fam_image} = "";
      $_->{fam_image_url} = "";
    }

    if (-e "$img_dir/$_->{sub_fam_id}.png") {
      $_->{sub_fam_image} = "$_->{sub_fam_id}.png";
      $_->{sub_fam_image_url} = "/api/image?dir=group_images&file=$_->{sub_fam_id}.png";
    } else {
      $_->{sub_fam_image} = "";
      $_->{sub_fam_image_url} = "";
    }
  }

  return $s->json($recs);
}

# curl -X GET "http://localhost:3041/api/image?dir=group_images&file=5.png"
# curl -X GET "http://localhost:3041/api/image?dir=product_images&file=5.png"
sub image {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  #my $p = $req->json;
  my $p = $req->params->to_hash;

  $p->{dir} ||= "";
  $p->{file} ||= "";

  return $s->json({ error => 'missing "dir" parameter...' }) unless $p->{dir};
  return $s->json({ error => 'missing "file" parameter...' }) unless $p->{file};

  my $path = $s->machine->server_dir_data() . "/" . $p->{dir} . "/" . $p->{file};

  if (-e $path) {
    $s->render_file('filepath' => $path);
  }
  else {
    return $s->json({ error => 'image not found... ' . $path });
  }
}

# curl -X POST "http://localhost:3041/api/stock_in" -H "Content-Type: application/json" -d '{"product":"1227","quantity": 2}'
sub stock_in {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{product} ||= "";
  $p->{quantity} ||= "";

  return $s->json({ error => 'missing parameters...' })
    unless $p->{product} && $p->{quantity};

  my $rec = $db->select(
    "SELECT id FROM products WHERE deleted = 0 AND id = ?",
    $p->{product},
  );

  return $s->json({ error => 'invalid product...' }) unless scalar @$rec;

  $db->do(qq{
    UPDATE products
    SET stock_use = 1, stock_current = stock_current + $p->{quantity}
    WHERE id = ?
  }, $p->{product});

  return $s->json({ success => 1 });
}

# curl -X POST "http://localhost:3041/api/stock_out" -H "Content-Type: application/json" -d '{"product":"1227","quantity": 2}'
sub stock_out {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{product} ||= "";
  $p->{quantity} ||= "";

  return $s->json({ error => 'missing parameters...' })
    unless $p->{product} && $p->{quantity};

  my $rec = $db->select(
    "SELECT id, stock_current FROM products WHERE deleted = 0 AND id = ?",
    $p->{product},
  );

  return $s->json({ error => 'invalid product...' }) unless scalar @$rec;

  my $qty = $rec->[0]->{stock_current};

  if ($qty <= 0) {
    return $s->json({ error => 'product has no stock...' });
  }

  $qty .= $p->{quantity};
  $qty = 0 if $qty < 0;

  $db->do(qq{
    UPDATE products
    SET stock_use = 1, stock_current = $qty
    WHERE id = ?
  }, $p->{product});

  return $s->json({ success => 1 });
}

# curl -X GET "http://localhost:3041/api/stock_current"
sub stock_current {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->params->to_hash;

  $p->{extra_data_fields} ||= "";
  $p->{extra_data_values} ||= "";

  my %ed_fields = ();
  my %ed_values = ();

  if ($p->{extra_data_fields}) {
    my @fields = split /,/, $p->{extra_data_fields};
    my @values = split /,/, $p->{extra_data_values};

    if (scalar @fields == scalar @values) {
      for (my $i=0; $i < scalar @fields; $i++) {
        $ed_fields{$fields[$i]} = $i;
      }

      for (my $i=0; $i < scalar @values; $i++) {
        $ed_values{$i} = $values[$i];
      }
    }
  }

  my $products_extra_data = _get_products_extra_data($db);

  my $recs = $db->select(qq{
    SELECT sf.name AS sub_name, sf.id AS sub_id, f.id AS top_id, f.name AS top_name,
      f.button_bg_color AS top_bg_color, f.button_color AS top_color,
      sf.button_color AS sub_color, sf.button_bg_color AS sub_bg_color,
      sf.priority AS sub_priority, f.priority AS top_priority, p.id, p.name,
      p.sell_vat1, p.sell_vat2, p.sell_price1, p.sell_price2, p.sell_price3,
      p.sell_price4, p.sell_price5, p.sell_price_menu, p.is_message, p.is_extra,
      p.barcode, p.handy_plu, p.is_menu, p.is_weight, p.ask_price, p.which_extras,
      p.button_color AS color, p.button_bg_color AS bg_color, p.stock_use,
      p.stock_min, p.stock_current, p.button_text, p.parent_product
    FROM product_groups pg
    LEFT JOIN products p ON (pg.product_id = p.id)
    LEFT JOIN groups sf ON (pg.group_id = sf.id)
    LEFT JOIN groups f ON (sf.parent = f.id)
    WHERE p.deleted = 0 AND f.deleted = 0 AND sf.deleted = 0 AND
      p.name <> '' AND f.name <> '' AND sf.name <> '' AND
      p.name <> '--' AND f.name <> '--' AND sf.name <> '--' AND
      p.stock_use = 1
    ORDER BY f.priority DESC, f.name, sf.priority DESC, sf.name, p.priority DESC, p.name
  });

  my @final = ();

  for (@$recs) {
    $_->{button_text} ||= "";
    $_->{product_extra_data} = exists $products_extra_data->{$_->{id}} ? $products_extra_data->{$_->{id}} : {};

    # lets try to filter products extra data
    if (scalar keys %ed_fields) {
      foreach my $field_name (keys %ed_fields) {
        my $field_idx = $ed_fields{$field_name};
        my $field_value = $ed_values{$field_idx};

        if (exists $_->{product_extra_data}->{$field_name} && $_->{product_extra_data}->{$field_name} eq $field_value) {
          push @final, $_;
        }
      }
    }
    else {
      push @final, $_;
    }
  }

  return $s->json(\@final);
}

# curl -X POST "http://localhost:3041/api/daily_special_qty" -H "Content-Type: application/json"
# curl -X POST "http://localhost:3041/api/daily_special_qty" -H "Content-Type: application/json" -d '{"product":"1227"}'
sub daily_special_qty {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{product} ||= "";
  my $recs;

  if ($p->{product}) {
    $recs = $db->select(
      "SELECT id FROM products WHERE deleted = 0 AND id = ?",
      $p->{product},
    );

    return $s->json({ error => 'invalid product...' }) unless scalar @$recs;

    $recs = $db->select(qq{
      SELECT ps.product_id AS product, ps.max_qtty AS qtty
      FROM product_daily_specials ps
      LEFT JOIN products p ON (ps.product_id = p.id)
      WHERE p.deleted = 0 AND ps.product_id = ?
    }, $p->{product});

    return $s->json($recs);
  }

  $recs = $db->select(qq{
    SELECT ps.product_id AS product, ps.max_qtty AS qtty
    FROM product_daily_specials ps
    LEFT JOIN products p ON (ps.product_id = p.id)
    WHERE p.deleted = 0
  });

  return $s->json($recs);
}

# curl -X POST "http://localhost:3041/api/daily_special_qty_in" -H "Content-Type: application/json" -d '{"product":"1227","quantity": 2}'
sub daily_special_qty_in {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{product} ||= "";
  $p->{quantity} ||= "";

  return $s->json({ error => 'missing parameters...' })
    unless $p->{product} && $p->{quantity};

  my $rec = $db->select(
    "SELECT id FROM products WHERE deleted = 0 AND id = ?",
    $p->{product},
  );

  return $s->json({ error => 'invalid product...' }) unless scalar @$rec;

  $rec = $db->select(
    "SELECT * FROM product_daily_specials WHERE product_id = ?",
    $p->{product},
  );

  if (scalar @$rec) {
    $db->do(qq{
      UPDATE product_daily_specials
      SET max_qtty = max_qtty + $p->{quantity}
      WHERE id = ?
    }, $p->{product});
  }
  else {
    return $s->json({ error => 'product not found in product_daily_specials...' })
      unless scalar @$rec;
  }

  return $s->json({ success => 1 });
}

# curl -X POST "http://localhost:3041/api/daily_special_qty_out" -H "Content-Type: application/json" -d '{"product":"1227","quantity": 2}'
sub daily_special_qty_out {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{product} ||= "";
  $p->{quantity} ||= "";

  return $s->json({ error => 'missing parameters...' })
    unless $p->{product} && $p->{quantity};

  my $rec = $db->select(
    "SELECT id FROM products WHERE deleted = 0 AND id = ?",
    $p->{product},
  );

  return $s->json({ error => 'invalid product...' }) unless scalar @$rec;

  $rec = $db->select(
    "SELECT max_qtty FROM product_daily_specials WHERE product_id = ?",
    $p->{product},
  );

  if (scalar @$rec) {
    my $qty = $rec->[0]->{max_qtty};

    if ($qty <= 0) {
      return $s->json({ error => 'product has no quantities available...' });
    }

    $qty -= $p->{quantity};
    $qty = 0 if $qty < 0;

    $db->do(qq{
      UPDATE product_daily_specials
      SET max_qtty = $qty
      WHERE id = ?
    }, $p->{product});
  }
  else {
    return $s->json({ error => 'product not found in product_daily_specials...' })
      unless scalar @$rec;
  }

  return $s->json({ success => 1 });
}

# curl -X GET "http://localhost:3041/api/db_table?table=products" \
sub db_table {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $p = $req->params->to_hash;
  #my $p = $req->json;

  $p->{table} ||= "";

  if (! $p->{table}) {
    return $s->json({ error => 'missing table parameter...' });
  }

  my $db = $s->db();

  my $recs = [];

  eval {
    $recs = $db->select("SELECT * FROM $p->{table} WHERE deleted = 0");
  };

  if ($@) {
    eval {
      $recs = $db->select("SELECT * FROM $p->{table}");
    };

    $recs = [] if $@;
  }

  return $s->json({ $p->{table} => $recs });
}

=pod
curl -X POST "http://localhost:3041/api/check_create" -H 'Content-Type: application/json' --data-binary @- << EOF
{
  "area": 2,
  "clerk": 16,
  "station": 70,
  "customer":{
    "name":"",
    "nif":"",
    "address":"",
    "postal_code":"",
    "city":""
  },
  "products":[
    {
      "id": 1,
      "quantity": 2,
      "price": 5,
      "vat": 13
    }
  ],
  "payment":[
    {
      "media": "DINHEIRO",
      "amount": 2.50
    },
    {
      "media": "CARTAO DEBITO",
      "amount": 2.50
    }
  ]
}
EOF
=cut
sub check_create {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  my $p = $req->json;
  #my $p = $req->params->to_hash;

  $p->{save_to_hdd} ||= 0;
  $p->{print_send_to} ||= 0;
  $p->{area} ||= 0;
  $p->{clerk} ||= 0;
  $p->{station} ||= 70;
  $p->{payment} ||= [];
  $p->{finalize} ||= 0;

  #open(F, ">> /tmp/mm.txt");
  #print F Dumper($p);
  #close(F);

  if (! $p->{clerk}) {
    return $s->json({ error => 'missing clerk parameter...' });
  }

  if (! scalar @{$p->{products}}) {
    return $s->json({ error => 'missing products parameter...' });
  }

  if ($p->{finalize}) {
    if (! scalar @{$p->{payment}}) {
      return $s->json({ error => 'missing payment parameter...' });
    }
  }

  my $area_dir = "/opt/pos/server/data/areas/$p->{area}";

  if (! -d $area_dir) {
    return $s->json({ error => 'invalid area...' });
  }

  #my $machine = $s->machine();
  my $info = $s->pos_config_loaded();

  my $new_id = _find_check_nextid($area_dir);

  my $f = "$area_dir/$new_id";
  my $o = App::POS::Check->new( file => $f );

  my $business_date = date_based_on_closing_hour(
    strftime("%Y-%m-%d %H:%M:%S",localtime),
    $info->{END_BUSINESS_HOUR} . ":00",
  );

  my @products = ();
  my @payments = ();
  my $products_extra_data = {};
  my $extra_data = {};

  #
  # header
  #

  my @header = $o->generate_empty_header(
    strftime("%Y-%m-%d %H:%M:%S", localtime),
    $business_date,
    $p->{clerk},
    $p->{area},
    0
    # $p->{station}
  );

  #
  # handle products
  #

  my $i = 0;

  foreach my $r (@{$p->{products}}) {
    my $gbi = strftime("%Y%m%d%H%M%S", localtime) . rand();
    $gbi =~ s/\.//g;

    my $datetime = strftime("%Y-%m-%d %H:%M:%S", localtime);
    my( $date, $hour ) = $datetime =~ /^(.*?) (.*?)$/;

    $r->{id} ||= 0;
    $r->{quantity} ||= 0;
    next unless $r->{id} && $r->{quantity};
    $r->{price} ||= 0;
    $r->{vat} ||= 0;
    $r->{discount} ||= 0;
    $r->{extra} ||= 0;

    push @products, [
      $i,
      $r->{id},
      $hour,
      $r->{quantity},
      $r->{price},
      $r->{discount},
      $r->{vat},
      $p->{clerk},
      "",                         # Order group description (Primeros, Secundos, etc)
      "",                         # Group / dept where product was registered. Can be null if product was registered after a search, for example
      1,                          # Operation Type
      "",                         # Discount Txt
      $p->{station},              # station
      $r->{extra} ? 'EXTRA' : "", # Text Extra / Menu / Notas - EXTRA | MENU
      0,                          # Inside Menu (0 / 1)
      0,                          # Was holded already
      1,                          # Price used on the sale
      $business_date,
      $gbi,
    ];

    $i++;
  }

  #
  # handle customer
  #

  if (scalar keys %{ $p->{customer} }) {
    $p->{customer}->{name} ||= "";
    $p->{customer}->{address} ||= "";
    $p->{customer}->{city} ||= "";
    $p->{customer}->{postal_code} ||= "";
    $p->{customer}->{nif} ||= "";

    $p->{customer}->{name} = my_conv($p->{customer}->{name})
      if $p->{customer}->{name};
    $p->{customer}->{address} = my_conv($p->{customer}->{address})
      if $p->{customer}->{address};
    $p->{customer}->{city} = my_conv($p->{customer}->{city})
      if $p->{customer}->{city};

    if ($p->{customer}->{nif}) {
      my $c = $p->{customer};

      my $customer = $db->select(
        "SELECT id FROM customers WHERE nif = ? AND deleted = 0",
        $c->{nif},
      );

      my $cid = "";

      if (! scalar @$customer) {
        $cid = $db->next_id("customers");

        $db->do(qq{
          INSERT INTO customers (
            id, nif, name, address, city, postal_code
          ) VALUES (
            ?, ?, ?, ?, ?, ?
          )
        }, $cid, $c->{nif}, fix_encoding($c->{name}), fix_encoding($c->{address}),
          fix_encoding($c->{city}), fix_encoding($c->{postal_code}));

      }
      else {
        $cid = $customer->[0]->{id};

        $db->do(qq{
          UPDATE customers
          SET name = ?, address = ?, city = ?, postal_code = ?
          WHERE id = ?
        }, fix_encoding($c->{name}), fix_encoding($c->{address}),
          fix_encoding($c->{city}), fix_encoding($c->{postal_code}), $cid);
      }

      $header[11] = $cid;
      $header[12] = $c->{name};
      $header[13] = $c->{nif};
    }
  }

  #
  # handle payment
  #

  if ($p->{finalize}) {
    foreach my $p (@{ $p->{payment} }) {
      push @payments, [ $p->{media}, $p->{amount}, "" ];
    }
  }

  #
  # build data
  #

  if ($p->{save_to_hdd}) {
    $extra_data->{save_to_hdd} = $p->{save_to_hdd};
  }

  if ($p->{print_send_to}) {
    $extra_data->{print_send_to} = $p->{print_send_to};
  }

  $extra_data->{from_api} = 1;

  my %data = (
    header   => \@header,
    details  => \@products,
    footers  => \@payments,
    products_extra_data  => {},
    extra_data  => $extra_data,
  );

  $o->set_data(\%data);

  if (! $p->{finalize}) {
    $data{extra_data}->{bill_is_out} = 1;
  }

  $o->save();

  _check_hold($area_dir, $p->{station}, $p->{area}, $new_id);

  if ($p->{finalize}) {
    # sleep 2; # we need this sleep so Handlers can process the orders and generate saved contents
    $o->finalize();
  } else {
    _print_bill($p->{area}, $new_id);
  }

  _tables_refresh();

  return $s->json({ success => 1, check_id => $new_id, o => $o });
}

sub _print_bill_old {
  my( $dir, $station, $area, $check_id ) = @_;
  #filePrint = Geral.SERVER_DATA_PATH() &/ "tmp" &/ print_notclosed_check & "#" & Globais.STATION_NUMBER & "#" & check.area & "#" & isInt & "#" & dontPrt & "#" & check.id & "#0#" & Globais.STATION_PRINT_CHECKS & ".txt"
  my $bill_file = "$dir/print_notclosed_check#$station#$area#0#1#$check_id#0#0.txt";
  print STDERR "################## $bill_file\n";
  write_file($bill_file, 1);
}

sub _tables_refresh {
  my @stations = read_dir('/opt/pos/server/data/registered_stations');
  write_file("/opt/pos/server/data/tmp/tables_refresh#0.txt", "1");

  foreach my $st (@stations) {
    write_file("/opt/pos/server/data/tmp/tables_refresh#$st.txt", "1");
  }
}

sub _print_bill {
  my( $area, $checknum ) = @_;

  my $sock = IO::Socket::INET->new(
    PeerAddr => '127.0.0.1',
    PeerPort => '8088',
    Proto => 'tcp',
    Timeout => 5,
  );

  if (defined $sock && $sock) {
    print $sock "#PRINTBILL#$area#$checknum\n" if defined $sock && $sock;
    $sock->close();
  }
  else {
    print STDERR ">> _print_bill - error connecting to port 8088...\n";
  }
}

sub _check_hold {
  my( $dir, $station, $area, $checknum ) = @_;

  #/opt/pos/server/data/areas/1/8.0.hold
  write_file("$dir/$checknum.$station.hold", localtime(time));

  #/opt/pos/server/data/areas/1/8.0.hold.check
  copy("$dir/$checknum", "$dir/$checknum.$station.hold.check");

  #/opt/pos/server/data/areas/1/8
  #/opt/pos/server/data/areas/1/8.total

=pod
  #system('echo "#CHECKHOLD#'.$area.'#'.$checknum.'" | timeout 0.5 nc 127.0.0.1 8088');

  my $sock = IO::Socket::INET->new(
    PeerAddr => '127.0.0.1',
    PeerPort => '8088',
    Proto => 'tcp',
    Timeout => 5,
  );

  if (defined $sock && $sock) {
    print $sock "#CHECKHOLD#$area#$checknum\n";
    $sock->close();
  }
  else {
    print STDERR ">> _check_hold - error connecting to port 8088...\n";
  }
=cut
}

sub file_delete {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  #my $p = $req->json;
  my $p = $req->params->to_hash;

  $p->{file} ||= "";
  return $s->json({ error => 'missing file parameter...' }) unless $p->{file};

  my $full_f = $s->machine->server_dir_tmp() . "/" . $p->{file};

  if (! -e $full_f) {
    return $s->json({ error => "can't find file - $full_f" });
  }

  unlink $full_f;

  return $s->json({ success => 1 });
}

sub file_get {
  my $s = shift;
  my $req = $s->req;
  my $config = $s->config; # app config
  my $db = $s->db;
  #my $p = $req->json;
  my $p = $req->params->to_hash;

  $p->{remove_after_get} ||= 0;
  $p->{file} ||= "";
  return $s->json({ error => 'missing file parameter...' }) unless $p->{file};

  my $full_f = $s->machine->server_dir_tmp() . "/" . $p->{file};

  if (! -e $full_f) {
    return $s->json({ error => "can't find file - $full_f" });
  }

  if ($p->{remove_after_get}) {
    my $cnt = read_file($full_f);
    unlink $full_f;
    return $s->text($cnt);
  } else {
    $s->render_file('filepath' => $full_f);
  }
}

sub _find_check_nextid {
  my $dir = shift;
  my $id = 1;

  my $f = $dir."/nextid";

  if (-e $f) {
    my $tmpid = read_file($dir."/nextid");
    $tmpid =~ s/\n//g;
    $tmpid =~ s/\r//g;
    $tmpid ||= 1;
    $tmpid++;
    $id = $tmpid;
  }

  write_file($f, "$id\n");

  return $id;
}

sub _get_products_extra_data {
  my $db = shift;

  my $products_extra_data = {};

  my $tmp = $db->select(qq{
    SELECT p.id, ped.field_name, ped.field_value
    FROM products_extra_data ped
    LEFT JOIN products p ON (ped.product_id = p.id)
    WHERE p.deleted = 0
  });

  for (@$tmp) {
    $_->{field_name} = "" unless defined $_->{field_name};
    next unless $_->{field_name};
    $_->{field_value} = "" unless defined $_->{field_value};
    $products_extra_data->{$_->{id}}->{$_->{field_name}} = $_->{field_value};
  }

  return $products_extra_data;
}

1

