#!/usr/bin/perl

use strict;
use warnings;
use open ':std', ':encoding(UTF-8)';

use File::Basename;
use File::Find::Rule;
use Capture::Tiny ':all';
use DateTime::Format::DateParse;

use lib '/app/tools/common/lib';
use Common::Session;

use lib '/app/tools/admin/lib';
use Admin::BMan;

my ( $opt, $usage ) = clopt(
    [ 'dryrun|d'                    => 'Dryrun of the backup - STDOUT only' ],
    [ 'force|F'                     => 'Force S3 copy' ],
    [ 'restoredir|b=s'              => 'Restore dir - default in config file' ],
    [ 'schema|s=s'                  => 'Schema to restore', { 'required' => 1 } ],
    [ 'skipdbcreate|skip-db-create' => 'Skip creating the schema on localhost' ],
    [ 'skipfiles|skip-files'        => 'Skip getting the S3 files' ],
    [ 'verbose|v'                   => 'Verbose' ],
    [ 'day|y=s'                     => 'Date to restore', { 'required' => 1 } ],
    [ 'help|?|h'                    => "print usage message and exit" ]
);
logMessage( 'info', $usage->text, 'options' ), exit if $opt->help;

my $schemas;
if ( $opt->schema =~ m/,/ ) {
    $schemas = [ split ',', $opt->schema ];
} else {
    push @{$schemas}, $opt->schema;
}

eval {

    $opt->{'verbose'} = 1 if $opt->dryrun;

    my $dbx  = Common::Session::getdbx('admindb');
    my $bman = Admin::BMan->new($opt);
    my $conf = $bman->config;
    my $rdir = $opt->restoredir || $conf->restoredir;

    foreach my $schema ( @{$schemas} ) {
        $schema = uc( $schema );

        my $db = $dbx->resultset('Report::DDb')->search( { 'db_name' => $schema } )->first;
        if ( not defined $db ) {
            logMessage( 'fatal', $schema . ' is not in the report.d_db dimension' );
            next;
        }

        my $dt   = DateTime::Format::DateParse->parse_datetime( $opt->day );
        my $rset = $dbx->resultset('Report::SysDbBackup')->search( {
                '-and' => [
                    'd_db_id' => $db->d_db_id,
                    \[ 'DATE(backup_datetime) = ?', [ {} => $dt->date ] ]
                ]
            }
        );

        my $files;
        while ( my $row = $rset->next ) {
            $files = {
                'datafile'   => $row->data_filename,
                'schemafile' => $row->schema_filename,
            };
        }
        if ( not defined $files ) {
            $bman->logtext( "No files matched $schema : " . $opt->day, "fatal" );
            next;
        }

        ## get the S3 files and uncompress them
        if ( not $opt->{'skipfiles'} ) {
            foreach my $k ( sort keys %{$files} ) {
                my $file = "$rdir/$files->{$k}";

                my $basename = File::Basename::basename($file);
                my ($_toext) = $basename =~ m!(.*)\.sql.gz$!;

                ## check to ensure the files aren't already in the /restore directory
                my $gz_file  = join '/', ( $rdir, "${_toext}.gz" );
                my $sql_file = join '/', ( $rdir, "${_toext}.sql" );
                if ( not $opt->force and ( -e $gz_file or -e $sql_file ) ) {
                    $bman->logtext( "A $rdir/$_toext.sql.(gz) file exists use -F to force s3 copy", "error" );
                    next;
                }

                ## get source file from S3 bucket
                my $src_opts = $opt->dryrun ? '--dry-run' : '--only-show-errors';
                my $src_file = join '/', ( $conf->s3bucket, $schema, $dt->ymd(''), $basename );
                $bman->logtext("Getting $src_file");
                $bman->execute( $conf->s3copy, $src_file, $file, $src_opts );

                ## uncompress source if copied from S3
                if ( $opt->dryrun or -e $file ) {
                    $bman->logtext("Uncompressing $file");
                    $bman->execute( $conf->uncompress, $file );
                }

            }
        }

        if ( not $opt->skipdbcreate ) {
            $bman->logtext("Checking for $schema in local DB");
            my ( $dbh, $dbs ) = Common::DB::Connect->databases('localhost');
            if ( not grep /$schema/, @{ $dbs->{'all'} } ) {
                $bman->logtext( "Create $schema on localhost", "warn" );
                my $sql = (qq/"CREATE DATABASE $schema CHARACTER SET utf8 COLLATE utf8_general_ci"/);
                $bman->execute( $conf->exec_restore, '-e', $sql );
            }

            my $r_schema_file = $files->{'schemafile'};
            $r_schema_file =~ s/\.gz//;
            $bman->logtext("Restoring $schema table structures");
            $bman->execute( $conf->exec_restore, "-D $schema -A <", "$rdir/$r_schema_file" );

            my $r_data_file = $files->{'datafile'};
            $r_data_file =~ s/\.gz//;
            $bman->logtext("Restoring $schema data");
            $bman->execute( $conf->exec_restore, "-D $schema -A <", "$rdir/$r_data_file" );
        }

        $bman->finish;
    }

};
if ($@) {
    logMessage( 'error', $@ );
    exit 1;
}
