package Pcore::App::MySQL;

use Pcore -class;

extends qw[Pcore::App::Alien];

has '+name' => ( default => 'mysql' );
has '+ns'   => ( default => 'Pcore::MySQL' );

our $CFG = {
    MYSQL => {    #
        MYSQL_VER => undef,
        SERVER    => {},
    }
};

# CLI
sub cli_name ($self) {
    return 'nginx';
}

# APP
around _build_cfg => sub ( $orig, $self ) {
    return P->hash->merge(
        $self->$orig,
        $CFG,
        {   MYSQL => {
                SERVER => {
                    basedir    => '/usr/',
                    datadir    => $self->alien_dir,
                    pid_file   => $self->app_dir . 'mysql.pid',
                    user       => 'nobody',
                    plugin_dir => '/usr/lib64/mysql/plugin/',

                    sql_mode                      => 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION',
                    character_set_server          => 'utf8',
                    collation_server              => 'utf8_general_ci',
                    log_output                    => 'FILE',
                    log_error                     => $ENV->{LOG_DIR} . $self->name . q[-mysql-error.log],
                    log_warnings                  => 1,
                    general_log                   => 0,
                    general_log_file              => $ENV->{LOG_DIR} . $self->name . q[-mysql-general.log],
                    slow_query_log                => 1,
                    slow_query_log_file           => $ENV->{LOG_DIR} . $self->name . q[-mysql-slow-queries.log],
                    long_query_time               => 2,
                    log_short_format              => 1,
                    log_queries_not_using_indexes => 1,
                    max_connections               => 200,

                    port                    => 3306,
                    socket                  => q[/tmp/] . $self->name . '.sock',
                    key_buffer_size         => '200M',
                    max_allowed_packet      => '32M',
                    table_open_cache        => '8192',
                    tmp_table_size          => '128M',
                    max_heap_table_size     => '128M',
                    sort_buffer_size        => '2M',
                    read_buffer_size        => '2M',
                    read_rnd_buffer_size    => '8M',
                    myisam_sort_buffer_size => '64M',
                    thread_cache_size       => '8',
                    query_cache_size        => '128M',
                    query_cache_limit       => '16M',
                    join_buffer_size        => '64M',

                    innodb_buffer_pool_size         => '700M',
                    innodb_additional_mem_pool_size => '20M',
                    innodb_log_file_size            => '200M',    # set .._log_file_size to 25 % of buffer pool size
                    innodb_log_buffer_size          => '8M',
                    innodb_file_per_table           => 1,

                    lower_case_table_names => 1,

                    # enable performance schema
                    performance_schema => 1,
                },
            }
        }
    );
};

around _create_local_cfg => sub ( $orig, $self ) {
    my $local_cfg = {
        MYSQL => {    #
            SERVER => $self->cfg->{MYSQL}->{SERVER},
        },
    };

    return P->hash->merge( $self->$orig, $local_cfg );
};

sub _build_alien_dir ($self) {
    return $self->app_dir . 'mysql-data/';
}

sub _build_alien_bin_path ($self) {
    return '/usr/sbin/mysqld';    # native MariaDB repo
}

sub _build_alien_cfg_path ($self) {
    return $self->app_dir . 'mysql.conf';
}

around app_build => sub ( $orig, $self ) {
    $self->$orig;

    $self->_appx_report_info(q[System-wide mysql distribution is used. Perform "yum -y install MariaDB-server" manually]);

    return;
};

around app_deploy => sub ( $orig, $self ) {
    $self->$orig;

    $self->generate_alien_cfg;

    # check datadir
    if ( !-d $self->alien_dir ) {
        my $root_password = P->random->bytes_hex(32);

        my $SQL = <<"SQL";
USE mysql;
SET sql_mode='';

CREATE table temp AS SELECT * FROM mysql.user WHERE user='root' AND host='localhost';
UPDATE temp SET host='%';
INSERT INTO mysql.user SELECT * FROM temp;
DROP TABLE temp;
UPDATE mysql.user SET password=PASSWORD('$root_password') WHERE user='root';

DELETE FROM mysql.user WHERE user='';
DELETE FROM mysql.db WHERE user='';
DROP SCHEMA test;

FLUSH PRIVILEGES;
SQL

        P->sys->system( 'mysql_install_db', q[--defaults-file=] . $self->alien_cfg_path );

        open my $MYSQLD, '|-', $self->alien_bin_path . ' --defaults-file=' . $self->alien_cfg_path . '  --bootstrap --default-storage-engine=myisam --loose-skip-innodb --loose-skip-ndbcluster' or die;

        say {$MYSQLD} $SQL;

        close $MYSQLD or die;

        say qq[Root password: $root_password];

        P->file->write_bin( $self->app_dir . '.mysql_password', { mode => q[rw-------], umask => q[rw-------] }, $root_password );
    }

    return;
};

sub generate_alien_cfg ($self) {
    my $cfg = qq[[server]\n];

    for my $key ( sort grep { defined $self->cfg->{MYSQL}->{SERVER}->{$_} } keys %{ $self->cfg->{MYSQL}->{SERVER} } ) {
        my $mysql_key = $key =~ s/_/-/smgr;
        $cfg .= qq[$mysql_key = ] . $self->cfg->{MYSQL}->{SERVER}->{$key} . $LF;
    }

    $self->store_alien_cfg( \$cfg );

    return;
}

sub master_proc ($self) {
    return;
}

sub alien_proc ($self) {
    $self->generate_alien_cfg;

    exec $self->alien_bin_path, q[--defaults-file=] . $self->alien_cfg_path or die;
}

1;
## -----SOURCE FILTER LOG BEGIN-----
##
## PerlCritic profile "pcore-script" policy violations:
## ┌──────┬──────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
## │ Sev. │ Lines                │ Policy                                                                                                         │
## ╞══════╪══════════════════════╪════════════════════════════════════════════════════════════════════════════════════════════════════════════════╡
## │    2 │ 140                  │ ValuesAndExpressions::ProhibitNoisyQuotes - Quotes used with a noisy string                                    │
## └──────┴──────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
##
## -----SOURCE FILTER LOG END-----
__END__
=pod

=encoding utf8

=head1 NAME

Pcore::App::MySQL

=head1 SYNOPSIS

=head1 DESCRIPTION

=head1 ATTRIBUTES

=head1 METHODS

=head1 SEE ALSO

=cut
