package App::POS::DB::SQLite;

use strict;
use warnings;
use Data::Dumper;
use UUID::Tiny;
use File::Copy qw( move copy );
use FindBin qw( $Bin );
use Date::Calc qw( Date_to_Time Delta_Days Add_Delta_Days );

use base qw( App::POS::DB );

sub register_functions {
  my $self = shift;

  my $dbh = $self->dbh();

  my $sth = $dbh->prepare("PRAGMA cache_size = 200000") or die($dbh->errstr());
  $sth->execute();
  $sth = $dbh->prepare("PRAGMA default_synchronous = OFF") or die($dbh->errstr());
  $sth->execute();
  $sth = $dbh->prepare("PRAGMA synchronous = OFF") or die($dbh->errstr());
  $sth->execute();
  $sth = $dbh->prepare("PRAGMA count_changes = OFF") or die($dbh->errstr());
  $sth->execute();
  $sth = $dbh->prepare("PRAGMA temp_store = MEMORY") or die($dbh->errstr());
  $sth->execute();
}

sub next_id {
   my $s = shift;
   my( $table, $id_field ) = @_;
   my $dbh = $s->dbh();
   my $sth = $dbh->prepare("SELECT MAX(".$id_field.")+1 FROM ".$table)
     or die $dbh->errstr();
   $sth->execute() or die $sth->errstr();
   my $arr = $sth->fetchall_arrayref();
   my $id = $arr->[0]->[0];
   $id = 1 unless defined $id;
   return $id;
}


sub do_norep {
  my $s = shift;
  my( $q, @p ) = @_;

  my $dbh = $s->dbh();
  my $sth;
  
  eval {
    $sth = $dbh->prepare($q) or $s->abort($dbh->errstr());
    $sth->execute(@p);
  };

  if ($@) {
    print STDERR "ERROR... QUERY: $q, PARAMS: ".Dumper(\@p);
    die("SQL ERROR");
  }
}

sub select2 {
  my $s = shift;
  my( $q, $a, @p ) = @_;

  $a->{db_path} ||= undef;
  $a->{date_from} ||= undef;
  $a->{date_to} ||= undef;

  return unless defined $a->{date_from} && defined $a->{date_to} && defined $a->{db_path};

  my $recs = [];

  my $files = $s->_db_files_to_use( $a->{db_path}, $a->{date_from}, $a->{date_to} );

  foreach my $f (@$files) {
    my $dbh = _dbh($f);
    my $db = App::POS::DB::SQLite->new( dbh => $dbh );

    my $t = $db->select($q, @p);
    push @$recs, @$t;
  }

  return wantarray? @{$recs || []} : $recs;
}

sub _days_between_dates {
  my( $date1, $date2 ) = @_;

  my( $y1, $m1, $d1 ) = $date1 =~ /^(\d+)\-(\d+)\-(\d+)$/;
  my( $y2, $m2, $d2 ) = $date2 =~ /^(\d+)\-(\d+)\-(\d+)$/;

  return Delta_Days(($y2, $m2, $d2), ($y1, $m1, $d1));
}

sub _db_files_to_use {
  my $s = shift;
  my( $db_path, $date1, $date2 ) = @_;

  my $r = [];
  push @$r, $db_path."/iecr.db";

  my $tmp1 = $date1;
  my $tmp2 = $date2;

  $tmp1 =~ s/\-//g;
  $tmp2 =~ s/\-//g;

  my $cur_date = $date2;
  my $last_date = $date1;
  my %tmp = ();

  if ($tmp2 >= $tmp1) {
    my( $y, $m ) = $cur_date =~ /^(\d\d\d\d)\-(\d\d)\-/;
    $tmp{$y.$m} = 1;

    while ($cur_date ne $last_date) {
      my( $year, $month, $day ) = $cur_date =~ /^(\d+)\-(\d+)\-(\d+)/;
      my ($y, $m, $d) = Add_Delta_Days($year, $month, $day, -1);
      $cur_date = "$y-$m-$d";
      ( $y, $m ) = $cur_date =~ /^(\d\d\d\d)\-(\d\d)\-/;
      $tmp{$y.$m} = 1;
    }

    foreach my $k (keys %tmp) {
      push @$r, $db_path."/iecr_".$k.".db" if -e $db_path."/iecr_".$k.".db";
    }
  }

  return $r;
}

sub _dbh {
  my $path = shift;

  my $dsn = 'dbi:SQLite:dbname='.$path;
  my $dbh = DBI->connect( $dsn, '', '', { PrintError => 0, RaiseError => 1 } );

  return $dbh;
}

1;
