#!/usr/bin/perl

use strict;
use warnings FATAL => 'all';
use feature 'say';
use utf8;
use open qw(:std :utf8);
use lib::abs;
use Moment;
use Data::Dumper;
use HTTP::Tiny;
use File::Slurp;
use JSON::PP;
use Getopt::Long;

# global vars

# subs
sub get_beta_port {

    my $path = lib::abs::path('./../../../../');
    $path =~ /([0-9]{4})$/;

    my $port = $1;
    if ($port) {
        return $port;
    } else {
        die "Can't find beta port in $path";
    }

}

sub info {
    my ($message) = @_;

    say Moment->now()->get_iso_string() . ' ' . $message;
    return 1;
}

sub is_mysql_running {
    my ($mysql_port) = @_;

    my $exit_status = system("echo 'select 1' | mysql --host 127.0.0.1 --port $mysql_port &> /dev/null");
    if ($exit_status == 0) {
        return 1;
    } else {
        return 0;
    }
}

sub apply_all_migrations_if_needed {

    my $success = 0;

    my $port = get_beta_port();
    my $data = decode_json scalar read_file "/local/creator/meta/$port.json";

    my $db_type = $data->{db}->{type};
    die "Can't find db type" unless $db_type;

    my $mysql_port = $port - 300;

    if ($db_type eq 'docker') {
        foreach (1..15) {
            if (is_mysql_running($mysql_port)) {
                $success = 1;
                last;
            } else {
                info "MySQL server is not available.";
                sleep 60;
            }
        }
        if ($success) {
            if( -e 'bin/run_migrations.pl') {
                my $wm = $data->{db}->{with_manual} ? '' : '--without_manual';
                my $env = 'export FORCE_LOGGER_TO_SCREEN=1; export SKIP_SEND_TO_BK=1;';
                my $res = `docker exec -i ${port}_backend_1 /bin/bash -c '$env perl -Ilib bin/run_migrations.pl $wm --without_prompt --type=all --order=all'`;
                info $res;
                $success = !($? >> 8);
            } else {
                info 'Automigration script "bin/run_migrations.pl" was not found';
            }
        }
    } else {
        $success = 1;
    }

    return $success;
}

sub append_to_log {
    my (%opts) = @_;

    my $success = delete $opts{success};

    my $port = get_beta_port();

    my $json_coder = JSON::PP
        ->new
        ->canonical
        ;

    my $now = Moment->now();
    my $data = decode_json scalar read_file "/local/creator/meta/$port.json";

    my $elapsed = $now->get_timestamp() - Moment->new( iso_string => $data->{created} )->get_timestamp();

    my $log_line = $json_coder->encode({
        timestamp => $now->get_iso_string(),
        success => ($success ? JSON::PP::true : JSON::PP::false ),
        port => $port,
        elapsed => $elapsed,
        has_login => ($data->{created_by} ? JSON::PP::true : JSON::PP::false ),
        ($data->{created_by} ? (login => $data->{created_by}) : () ),
        full_info => $data,
    }) . "\n";

    write_file(
        sprintf('/local/creator/log/create.%s.jsonl', $now->get_d()),
        {
            append => 1,
        },
        $log_line,
    );
}

sub to_pretty_json {
    my ($data) = @_;

    my $json_coder = JSON::PP
        ->new
        ->pretty
        ->canonical
        ->indent_length(4)
        ;

    my $pretty_json = $json_coder->encode($data);

    return $pretty_json;
}

sub change_beta_status {
    my ($status) = @_;

    my $port = get_beta_port();

    my $file_name = sprintf('/local/creator/meta/%s.json', $port);
    my $data = decode_json scalar read_file $file_name;

    $data->{status} = $status;

    write_file(
        $file_name,
        {
            binmode => ':utf8',
        },
        to_pretty_json($data),
    );

    send_beta_status({
        'port'   => $port,
    });

    return 1;
}

sub send_beta_status {
    my ($opts) = @_;

    my $file_name = sprintf('/local/creator/meta/%s.json', $opts->{'port'});

    my $data = decode_json scalar read_file $file_name;

    delete $data->{'comment'};

    info('SEND STAT TO KRUSHER');
    my $res = HTTP::Tiny->new()->post(
        'https://krush.partner.yandex-team.ru/v3/logger/creator',
        {
            'headers'=> {'Content-type' => 'application/json'},
            'content' => JSON::PP->new->encode($data)
        }
    );
    info(Dumper($res));
}

# main
sub main {

    info('`make docker_restart` finished');

    my $exit_status;
    GetOptions(
        "exit_status=i" => \$exit_status,
    ) or die("Error in command line arguments\n");

    if (($exit_status // '') eq '0') {

        my $migrations_is_success = apply_all_migrations_if_needed();

        if ($migrations_is_success) {
            change_beta_status('running');
            info 'FINISHED. OK.';

            append_to_log(success => 1);
        } else {
            change_beta_status('build_fail');
            info 'FINISHED. FAIL.';
            append_to_log(success => 0);
        }

    } else {
        change_beta_status('build_fail');
        info 'FINISHED. FAIL.';
        append_to_log(success => 0);
    }

}

main();
__END__
