#!/usr/bin/perl

use Modern::Perl;

use Getopt::Long qw( GetOptions );
use MARC::Field;
use MARC::Record;
use Pod::Usage qw( pod2usage );
use Time::HiRes qw( gettimeofday );

use Koha::Script;
use C4::Context;
use C4::Biblio qw( GetMarcFromKohaField );
use C4::Items qw( ModItemFromMarc );
use Koha::Biblios;

=head1 NAME

batchRebuildBiblioTables.pl - rebuilds the non-MARC DB items table from the MARC values

You can/must use it when you change items mapping.

=head1 SYNOPSIS

batchRebuildItemsTables.pl [ -h ][ -c ][ -t ][ --where ]

 Options:
   -h --help       (or without arguments) shows this help message
   -c              Confirm: rebuild non marc DB (may be long)
   -t              test only, change nothing in DB
   --where         add where condition on default query (eg. --where 'biblio.biblionumber<100')

=cut

my $count      = 0;
my $errorcount = 0;
my $starttime  = gettimeofday;
my @errors;
my ( $confirm, $help, $test_parameter, $where );
GetOptions(
    'c'       => \$confirm,
    'help|h'  => \$help,
    't'       => \$test_parameter,
    'where:s' => \$where,
) or pod2usage(2);

pod2usage(1) if $help || ( !$confirm && !$test_parameter );
print "### Database will not be modified ###\n" if $test_parameter;

my $dbh = C4::Context->dbh;
my $schema = Koha::Database->schema;
$schema->txn_begin;

#sysprefs
C4::Context->disable_syspref_cache() if ( defined( C4::Context->disable_syspref_cache() ) );
my $CataloguingLog = C4::Context->preference('CataloguingLog');
my $mergelimit     = C4::Context->preference('AuthorityMergeLimit');
$dbh->do("UPDATE systempreferences SET value=0 WHERE variable='CataloguingLog'");
$dbh->do("UPDATE systempreferences SET value=0 where variable='AuthorityMergeLimit'");
unless ($test_parameter){
    $schema->txn_commit;
    $schema->txn_begin;
}
my ( $itemfield, $itemnumbersubfield ) = &GetMarcFromKohaField( "items.itemnumber" );

#dbh query init
my $query =
qq{SELECT biblio.biblionumber AS biblionumber, biblioitems.biblioitemnumber AS biblioitemnumber, biblio.frameworkcode AS frameworkcode FROM biblio JOIN biblioitems ON biblio.biblionumber=biblioitems.biblionumber};
$query .= qq{ WHERE $where } if ($where);

my $sth = $dbh->prepare($query);
$sth->execute();
while ( my ( $biblionumber, $biblioitemnumber, $frameworkcode ) = $sth->fetchrow ) {
    $count++;
    warn $count unless $count % 1000;
    my $biblio = Koha::Biblios->find($biblionumber);
    my $record = $biblio->metadata->record({ embed_items => 1 });

    unless ($record) { push @errors, "bad record biblionumber $biblionumber"; next; }

    unless ($test_parameter) {
        my $rqitemnumber = $dbh->prepare("SELECT itemnumber, biblionumber from items where itemnumber = ? and biblionumber = ?");
        foreach my $itemfield ( $record->field($itemfield) ) {
            my $marcitem = MARC::Record->new();
            $marcitem->encoding('UTF-8');
            $marcitem->append_fields($itemfield);
            my $itemnum;
            my @itemnumbers = $itemfield->subfield($itemnumbersubfield);
            foreach my $itemnumber (@itemnumbers) {
                $rqitemnumber->execute( $itemnumber, $biblionumber );
                if ( my $row = $rqitemnumber->fetchrow_hashref ) { $itemnum = $row->{itemnumber}; }
            }
            eval {
                if ($itemnum) { ModItemFromMarc( $marcitem, $biblionumber, $itemnum ) }
                else          { die("$biblionumber"); }
            };
            if ($@) { warn "Problem with : $biblionumber : $@"; warn $record->as_formatted; }
        }
    }

    unless ($test_parameter || $count % 1000) {
        $schema->txn_commit;
        $schema->txn_begin;
    }
}

my $sthCataloguingLog = $dbh->prepare("UPDATE systempreferences SET value=? WHERE variable='CataloguingLog'");
$sthCataloguingLog->execute($CataloguingLog);
my $sthmergelimit = $dbh->prepare("UPDATE systempreferences SET value=? WHERE variable='AuthorityMergeLimit'");
$sthmergelimit->execute($mergelimit);
$schema->txn_commit unless $test_parameter;
my $timeneeded = time() - $starttime;
print "$count MARC record done in $timeneeded seconds\n";
if ( scalar(@errors) > 0 ) {
    print "Some biblionumber could not be processed though: ", join( " ", @errors );
}
