<?php

$cms["modules"]["base.mod.php"] = array(
    "name"        => "base_module_name",
    "description" => "base_module_description",
    "files" => array(
        ".cms/css/base.less",
        ".cms/css/base.css",
        ".cms/mod/base.mod.php",
        ".cms/js/base.js",
        ".cms/lang/ru_RU.UTF-8/base.mod.php",
        ".cms/lang/en_US.UTF-8/base.mod.php",
        ".cms/lang/uk_UA.UTF-8/base.mod.php",
    ),
);

// Если модуль отключён – ничего не делаем
if ( ! empty($cms["config"]["base.mod.php"]["disabled"] ) ) {
    return;
}

// Устанавливаем значения по умолчанию
$defaults = array(
    "type" => "mysql",
    "host" => "localhost",
    "port" => "3306",
    "user" => "",
    "pass" => "",
    "base" => "",
);
foreach ( $defaults as $k => $v ) {
    if ( ! isset( $cms["config"]["base.mod.php"][$k] ) ) {
        $cms["config"]["base.mod.php"][$k] = $v;
    }
}
    
// Добавляем функции на хуки
if ( is_admin() ) {
    hook_add_fn( "admin_header", "cms_base_admin_header" );
    hook_add_fn( "admin", "cms_base_admin" );
    // Чтобы при написании модулей не делать в каждом подключение
    // API доступно только из админки
    hook_add_fn( "api",   "cms_base_connect", 5 );
    // Чтобы при написании модулей каждый сам не подключал
    hook_add_fn( "admin", "cms_base_connect", 5 );
}
hook_add_fn( "query", "cms_base_connect", 5 );

function cms_base_connect() {
    global $cms;

    if ( ! empty( $cms["config"]["base.mod.php"]["disabled"] ) ) {
        return false;
    }

    // Если уже подключено – возвращаем объект
    if ( isset( $cms["pdo"] ) && $cms["pdo"] instanceof PDO ) {
        return $cms["pdo"];
    }

    $cfg  = $cms["config"]["base.mod.php"];
    $type = $cfg["type"];
    $host = $cfg["host"];
    $port = $cfg["port"];
    $base = $cfg["base"];
    $user = $cfg["user"];
    $pass = $cfg["pass"];

    try {
        $dsn = "{$type}:host={$host};port={$port};dbname={$base}";
        // Для MySQL можно задать charset сразу в DSN
        if ( $type === "mysql" ) {
            $dsn .= ";charset=utf8mb4";
        }
        $pdo = new PDO( $dsn, $user, $pass, array(
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ) );
        $cms["pdo"] = $pdo;
        return $pdo;
    } catch ( PDOException $e ) {
        error_log( "PDO connection failed: " . $e->getMessage() );
        $cms["pdo"] = false; // Помечаем, что подключение не удалось
        return false;
    }
}

function cms_base_admin_header() {
    global $cms;
    if ( is_admin_header_on( "base.mod.php" ) ) {
        echo "        <link rel=stylesheet href='{$cms["base_path"]}css/base.css'>\n";
        echo "        <script src='{$cms["base_path"]}js/base.js'></script>\n";
    }
}

function cms_base_admin() {
    global $cms;

    /* ---------- Сохранение настроек ---------- */
    if ( ! empty($_POST["save_base_config"] ) ) {
        $cfg = &$cms["config"]["base.mod.php"];
        $cfg["type"] = trim( $_POST["type"] );
        $cfg["host"] = trim( $_POST["host"] );
        $cfg["port"] = trim( $_POST["port"] );
        $cfg["base"] = trim( $_POST["base"] );
        $cfg["user"] = trim( $_POST["user"] );
        $cfg["pass"] = trim( $_POST["pass"] );
        cms_save_config();

        /* ---------- Создание БД и пользователя ---------- */
        $trim_login = trim( $_POST["admin_login"] ); // php 5.2
        $trim_password = trim( $_POST["admin_password"] ); // php 5.2
        if ( ! empty( $trim_login ) && ! empty( $trim_password ) ) {
            try {
                $dsn = "{$_POST["type"]}:host={$cfg["host"]};port={$cfg["port"]}";
                $pdo = new PDO(
                    $dsn,
                    $_POST["admin_login"],
                    $_POST["admin_password"],
                    array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION )
                );

                if ( $cfg["type"] === "mysql" ) {
                    $base = '`' . str_replace( '`', '``', $cfg["base"] ) . '`';
                    $host = $pdo->quote( $cfg["host"] );
                    $user = $pdo->quote( $cfg["user"] );
                    $pass = $pdo->quote( $cfg["pass"] );
                    $pdo->exec( "CREATE DATABASE IF NOT EXISTS {$base}" );
                    $pdo->exec( "CREATE USER IF NOT EXISTS {$user}@'%' IDENTIFIED BY {$pass}" );
                    $pdo->exec( "GRANT ALL PRIVILEGES ON {$base}.* TO {$user}@'%'" );
                    $pdo->exec( "FLUSH PRIVILEGES" );
                } elseif ( $cfg["type"] === "pgsql" ) {
                    $base = '"' . str_replace( '"', '""', $cfg["base"] ) . '"';
                    $user = '"' . str_replace( '"', '""', $cfg["user"] ) . '"';
                    $pass = $pdo->quote( $cfg["pass"] );
                    // Создаем базу
                    $stmt = $pdo->prepare( "SELECT 1 FROM pg_database WHERE datname = ?" );
                    $stmt->execute( array( $cfg["base"] ) );
                    if ( ! $stmt->fetchColumn() ) {
                        // Если что-то менять, то проверять на обоих базах что нет ошибок
                        $pdo->exec( "CREATE DATABASE {$base} ENCODING 'UTF8'" );
                    }
                    // Создаем пользователя
                    $stmt = $pdo->prepare( "SELECT 1 FROM pg_roles WHERE rolname = ?" );
                    $stmt->execute( array( $cfg["user"] ) );
                    if ( ! $stmt->fetchColumn() ) {
                        $pdo->exec( "CREATE ROLE {$user} LOGIN PASSWORD {$pass}" );
                    }
                    // Выдаем привилегии
                    $pdo->exec( "GRANT ALL PRIVILEGES ON DATABASE {$base} TO {$user}" );
                    // Подключаемся к новой базе данных для предоставления прав на схему
                    $pdo_base = new PDO(
                        $dsn . ";dbname={$cfg["base"]}",
                        $_POST["admin_login"],
                        $_POST["admin_password"],
                        array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION )
                    );
                    // Предоставляем права на схему public
                    $pdo_base->exec( "GRANT USAGE, CREATE ON SCHEMA public TO {$user}" );
                }
            } catch ( PDOException $e ) {
                error_log( "Database creation failed: " . $e->getMessage() );
            }
        }

        // Подключаемся обычным пользователем
        if ( cms_base_connect() ) {
            cms_exec_sql_file( "{$cms['cms_dir']}/update.sql" );
            // Выполнить запросы в БД, находящиеся в файле update.sql
            $update_sql = "{$cms['cms_dir']}/update.sql";

            // При отображении боковой панели админки, шаблон не знает что это за пункт,
            // поэтому просто берет классы. И тут нужно убрать red раз подключение выполнено.
            if ( isset( $cms["config"]["base.mod.php"]["menu"]["base"]["classes"] ) ) {
                unset( $cms["config"]["base.mod.php"]["menu"]["base"]["classes"] );
                $saved = cms_save_config();
            }
        
            do_hook( "create_tables" );
        }

        $cms["status"] = "302";
        $cms["status_302_location"] = $cms["base_path"] . $cms["config"]["admin.mod.php"]["admin_url"];
        return;
    }

    /* ---------- Отображение формы ---------- */
    if ( is_admin_header_on( "base.mod.php" ) ) {

        $e_type = htmlspecialchars( $cms["config"]["base.mod.php"]["type"] );
        $e_host = htmlspecialchars( $cms["config"]["base.mod.php"]["host"] );
        $e_port = htmlspecialchars( $cms["config"]["base.mod.php"]["port"] );
        $e_base = htmlspecialchars( $cms["config"]["base.mod.php"]["base"] );
        $e_user = htmlspecialchars( $cms["config"]["base.mod.php"]["user"] );
        $e_pass = htmlspecialchars( $cms["config"]["base.mod.php"]["pass"] );
        $page = "

<form method=post>
    <div class='basic panel'>
        <label>
            <div class=title>" . __("base_driver") . "</div>
            <input name=type type=text value='{$e_type}' placeholder=mysql>
        </label>
        <label>
            <div class=title>" . __("server_address") . "</div>
            <input name=host type=text value='{$e_host}' placeholder=localhost>
        </label>
        <label>
            <div class=title>" . __("server_port") . "</div>
            <input name=port type=text value='{$e_port}' placeholder=3306>
        </label>
        <label>
            <div class=title>" . __("db_name") . "</div>
            <input name=base type=text value='{$e_base}'>
        </label>
        <label>
            <div class=title>" . __("db_user") . "</div>
            <input name=user type=text value='{$e_user}'>
        </label>
        <label>
            <div class=title>" . __("db_password") . "</div>
            <div class='password widget'>
                <input type=password name=pass value='{$e_pass}'>
                <div class=button><span></span></div>
            </div>
        </label>
        <button class=button name=save_base_config value=save><span>" . __("save") . "</span></button>
        <div class='pro button'><span>PRO</span></div>
    </div>

    <div class='pro panel'>
        <div class=create>" . __("create_db") . "</div>
        <label>
            <div class=title>" . __("admin_login") . "</div>
            <input name=admin_login type=text value>
        </label>
        <label>
            <div class=title>" . __("admin_passwd") . "</div>
            <div class='password widget'>
                <input name=admin_password type=password value>
                <div class=button><span></span></div>
            </div>
        </label>
        <button class=button name=save_base_config value=create><span>" . __("create_btn") . "</span></button>
    </div>
</form>";

        // Создать пункт в боковой панели
        if ( empty( $cms["config"]["base.mod.php"]["menu"]["base"] ) ) {
            $cms["config"]["base.mod.php"]["menu"]["base"] = array(
                "title"    => "base_module_name",
                "sort"     => 20,
                "section"  => "settings",
            );
            cms_save_config();
        }

        if ( cms_base_connect() === false ) {
            $cms["config"]["base.mod.php"]["menu"]["base"]["classes"] = "red";
        }

        $cms["admin_pages"]["base"] = $page;

    }
}
