<?php
function mj_config(): array {
    $file = __DIR__ . '/config.php';
    if (!file_exists($file)) {
        return ['installed' => false, 'base_url' => '', 'timezone' => 'Asia/Singapore'];
    }
    $config = require $file;
    if (!is_array($config)) { $config = []; }
    return array_merge(['installed'=>false,'base_url'=>'','timezone'=>'Asia/Singapore'], $config);
}

function mj_is_installed(): bool {
    $cfg = mj_config();
    return !empty($cfg['installed']) && file_exists(__DIR__ . '/config.php');
}

function mj_install_redirect_url(): string {
    // Always redirect to the real project /install/index.php, not a relative URL like /singapore/install/.
    $script = str_replace('\\','/', (string)($_SERVER['SCRIPT_NAME'] ?? ''));
    $dir = rtrim(str_replace('\\','/', dirname($script)), '/');
    $dir = preg_replace('#/(admin|ajax|api|cron)$#', '', $dir);
    $dir = rtrim((string)$dir, '/');
    if ($dir === '/' || $dir === '.' || $dir === '') { return '/install/index.php'; }
    return $dir . '/install/index.php';
}

function db(): PDO {
    static $pdo = null;
    if ($pdo instanceof PDO) { return $pdo; }
    $cfg = mj_config();
    if (empty($cfg['installed'])) {
        $target = mj_install_redirect_url();
        if (!headers_sent()) { header('Location: ' . $target); } else { echo '<script>location.href=' . json_encode($target) . ';</script>'; }
        exit;
    }
    $dsn = 'mysql:host=' . $cfg['db_host'] . ';dbname=' . $cfg['db_name'] . ';charset=utf8mb4';
    $pdoOpts = [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
    ];
    if (defined('PDO::MYSQL_ATTR_USE_BUFFERED_QUERY')) {
        $pdoOpts[PDO::MYSQL_ATTR_USE_BUFFERED_QUERY] = true;
    }
    $pdo = new PDO($dsn, $cfg['db_user'], $cfg['db_pass'], $pdoOpts);
    $tz = $cfg['timezone'] ?? 'Asia/Singapore';
    if ($tz) { @date_default_timezone_set($tz); }
    return $pdo;
}

function q(string $sql, array $params = []): PDOStatement {
    $stmt = db()->prepare($sql);
    try {
        $stmt->execute($params);
        return $stmt;
    } catch (Throwable $e) {
        // v3.0.4.2.8: safe SQL auto-repair for missing tables/columns, then retry once.
        if (function_exists('mj428_try_repair_sql_error') && mj428_try_repair_sql_error($e, $sql)) {
            $stmt = db()->prepare($sql);
            $stmt->execute($params);
            return $stmt;
        }
        throw $e;
    }
}

function one(string $sql, array $params = []): ?array {
    $row = q($sql, $params)->fetch();
    return $row ?: null;
}

function all_rows(string $sql, array $params = []): array {
    return q($sql, $params)->fetchAll();
}
