<?php
/**
 * Celena CMS — веб-установщик.
 * Шаги: проверка окружения → база данных → администратор → установка.
 *
 * Файл намеренно написан на консервативном синтаксисе (совместим с PHP 7.0+),
 * чтобы на старом PHP показать понятное сообщение, а не белый экран.
 * После успешной установки создаёт install.lock и удаляет сам себя.
 */

error_reporting(E_ALL);
ini_set('display_errors', '0');

$root = __DIR__;

// --- Уже установлено? Никакой повторной установки. ---
if (is_file($root . '/install.lock')) {
    http_response_code(403);
    header('Content-Type: text/html; charset=utf-8');
    echo '<!doctype html><meta charset="utf-8"><title>403</title>'
        . '<body style="font-family:system-ui;padding:40px;max-width:640px;margin:auto">'
        . '<h1>CMS уже установлена</h1>'
        . '<p>Найден файл <code>install.lock</code>. Повторная установка заблокирована.</p>'
        . '<p>Если нужно переустановить: удалите <code>install.lock</code> в корне сайта (и при необходимости очистите базу данных), затем обновите страницу.</p>'
        . '<p>Из соображений безопасности удалите файл <code>install.php</code> с рабочего сайта.</p></body>';
    exit;
}

// --- Минимальная версия PHP (проверяем ДО загрузки классов ядра). ---
if (version_compare(PHP_VERSION, '8.3.0', '<')) {
    http_response_code(500);
    header('Content-Type: text/html; charset=utf-8');
    echo '<!doctype html><meta charset="utf-8"><title>PHP</title>'
        . '<body style="font-family:system-ui;padding:40px;max-width:640px;margin:auto">'
        . '<h1>Требуется PHP 8.3 или новее</h1>'
        . '<p>Сейчас на сервере PHP ' . htmlspecialchars(PHP_VERSION, ENT_QUOTES, 'UTF-8') . '.</p>'
        . '<p>Переключите версию PHP в панели хостинга и обновите страницу.</p></body>';
    exit;
}

// --- Автозагрузчик ядра и сессия установщика. ---
require $root . '/core/Autoloader.php';
\Celena\Core\Autoloader::register($root);

session_name('celena_install');
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'httponly' => true, 'samesite' => 'Lax']);
session_start();

if (empty($_SESSION['csrf'])) {
    $_SESSION['csrf'] = bin2hex(random_bytes(32));
}
$csrf = (string) $_SESSION['csrf'];

$setup = new \Celena\Core\Install\SetupService($root);

/** Экранирование для HTML. */
function h(?string $v): string
{
    return htmlspecialchars((string) $v, ENT_QUOTES, 'UTF-8');
}

/** Значение POST-поля строкой. */
function post(string $key, string $default = ''): string
{
    $v = isset($_POST[$key]) ? $_POST[$key] : $default;
    return is_string($v) ? $v : $default;
}

$step = post('step', 'env');
$error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!hash_equals($csrf, post('_csrf'))) {
        $step = 'env';
        $error = 'Сессия устарела, начните заново.';
    }
} else {
    $step = 'env';
}

// Автоопределение URL сайта по текущему запросу.
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
    || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') ? 'https' : 'http';
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
$guessedUrl = $scheme . '://' . $host;

// Значения формы БД: из POST → из сессии → дефолты.
$savedDb = isset($_SESSION['db']) && is_array($_SESSION['db']) ? $_SESSION['db'] : [];
$dbForm = [
    'driver' => post('db_driver', isset($savedDb['driver']) ? $savedDb['driver'] : 'mysql'),
    'host'   => post('db_host', isset($savedDb['host']) ? $savedDb['host'] : '127.0.0.1'),
    'port'   => post('db_port', isset($savedDb['port']) ? $savedDb['port'] : ''),
    'name'   => post('db_name', isset($savedDb['name']) ? $savedDb['name'] : 'celena'),
    'user'   => post('db_user', isset($savedDb['user']) ? $savedDb['user'] : ''),
    'pass'   => post('db_pass', isset($savedDb['pass']) ? $savedDb['pass'] : ''),
    'prefix' => post('db_prefix', isset($savedDb['prefix']) ? $savedDb['prefix'] : 'cl_'),
];

$installLog = [];
$selfDeleted = false;

// ---------------------------------------------------------------
// Обработка шагов
// ---------------------------------------------------------------

if ($step === 'db-save' && $error === '') {
    try {
        $db = $setup->normalizeDb($dbForm);
        $state = $setup->ensureDatabase($db);
        $_SESSION['db'] = $db;
        $_SESSION['db_created'] = ($state === 'created');
        $step = 'admin';
    } catch (\Throwable $e) {
        $error = $e->getMessage();
        $step = 'db';
    }
}

if ($step === 'run' && $error === '') {
    if (!isset($_SESSION['db']) || !is_array($_SESSION['db'])) {
        $step = 'db';
        $error = 'Параметры БД не найдены — заполните форму ещё раз.';
    } else {
        $pass1 = post('admin_pass');
        $pass2 = post('admin_pass2');
        if ($pass1 !== $pass2) {
            $error = 'Пароли не совпадают.';
            $step = 'admin';
        } else {
            try {
                $installLog = $setup->install(
                    $_SESSION['db'],
                    ['url' => post('app_url', $guessedUrl), 'name' => post('site_name', 'Мой сайт')],
                    ['email' => post('admin_email'), 'password' => $pass1, 'name' => post('admin_name')]
                );
                // Установка успешна: чистим сессию установщика и удаляем сам файл.
                $_SESSION = [];
                @session_destroy();
                $selfDeleted = @unlink(__FILE__);
                $step = 'done';
            } catch (\Throwable $e) {
                $error = $e->getMessage();
                $step = 'admin';
            }
        }
    }
}

if ($step === 'db' || $step === 'db-form') {
    $step = 'db';
    if ($error === '' && !$setup->environmentOk()) {
        $step = 'env';
        $error = 'Сначала устраните проблемы окружения.';
    }
}

$checks = $step === 'env' ? $setup->checkEnvironment() : [];
$envOk = $step === 'env' ? $setup->environmentOk() : true;

$stepNum = ['env' => 1, 'db' => 2, 'admin' => 3, 'done' => 4];
$current = isset($stepNum[$step]) ? $stepNum[$step] : 1;

header('Content-Type: text/html; charset=utf-8');
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
?>
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<title>Установка Celena CMS</title>
<style>
:root { --bg:#f4f6f9; --card:#fff; --text:#1c2430; --muted:#68758a; --line:#e3e8ef;
        --accent:#2563eb; --accent-h:#1d4ed8; --ok:#16a34a; --err:#dc2626; --warn:#d97706; }
* { box-sizing:border-box; }
body { margin:0; background:var(--bg); color:var(--text);
       font:15px/1.55 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif; }
.wrap { max-width:680px; margin:48px auto; padding:0 16px; }
.logo { text-align:center; margin-bottom:24px; }
.logo b { font-size:22px; letter-spacing:.4px; }
.logo span { color:var(--muted); font-size:13px; display:block; margin-top:2px; }
.card { background:var(--card); border:1px solid var(--line); border-radius:12px;
        padding:28px; box-shadow:0 1px 3px rgba(16,24,40,.06); }
h1 { font-size:19px; margin:0 0 18px; }
.steps { display:flex; gap:8px; margin-bottom:22px; }
.steps i { flex:1; height:4px; border-radius:2px; background:var(--line); font-style:normal; }
.steps i.on { background:var(--accent); }
table.checks { width:100%; border-collapse:collapse; }
table.checks td { padding:9px 6px; border-bottom:1px solid var(--line); vertical-align:top; }
table.checks tr:last-child td { border-bottom:0; }
.b { display:inline-block; font-size:12px; padding:2px 9px; border-radius:20px; white-space:nowrap; }
.b-ok { background:#e8f7ee; color:var(--ok); }
.b-err { background:#fdecec; color:var(--err); }
.b-warn { background:#fdf3e3; color:var(--warn); }
.muted { color:var(--muted); font-size:13px; }
label { display:block; font-size:13px; font-weight:600; margin:14px 0 5px; }
input[type=text], input[type=email], input[type=password], select {
  width:100%; padding:9px 12px; border:1px solid var(--line); border-radius:8px;
  font:inherit; background:#fff; }
input:focus, select:focus { outline:2px solid var(--accent); outline-offset:-1px; border-color:var(--accent); }
.row { display:flex; gap:12px; } .row > div { flex:1; }
.btn { display:inline-block; margin-top:22px; padding:10px 22px; border:0; border-radius:8px;
       background:var(--accent); color:#fff; font:inherit; font-weight:600; cursor:pointer; }
.btn:hover { background:var(--accent-h); }
.btn[disabled] { background:#b6c3d9; cursor:not-allowed; }
.alert { background:#fdecec; border:1px solid #f5c8c8; color:#991b1b;
         border-radius:8px; padding:11px 14px; margin-bottom:16px; font-size:14px; }
.note { background:#eef4ff; border:1px solid #d3e0fb; color:#1e3a8a;
        border-radius:8px; padding:11px 14px; margin-top:16px; font-size:13px; }
ul.log { margin:12px 0 0; padding-left:20px; }
ul.log li { margin:4px 0; }
a { color:var(--accent); }
.actions { text-align:right; }
</style>
</head>
<body>
<div class="wrap">
  <div class="logo"><b>Celena CMS</b><span>мастер установки</span></div>
  <div class="card">
    <div class="steps"><?php for ($i = 1; $i <= 4; $i++): ?><i class="<?= $i <= $current ? 'on' : '' ?>"></i><?php endfor; ?></div>

    <?php if ($error !== ''): ?><div class="alert"><?= h($error) ?></div><?php endif; ?>

    <?php if ($step === 'env'): ?>
      <h1>Шаг 1 из 3 — проверка окружения</h1>
      <table class="checks">
        <?php foreach ($checks as $c): ?>
        <tr>
          <td><?= h($c['label']) ?><br><span class="muted"><?= h($c['details']) ?></span></td>
          <td style="text-align:right">
            <?php if ($c['ok']): ?><span class="b b-ok">OK</span>
            <?php elseif ($c['required']): ?><span class="b b-err">Ошибка</span>
            <?php else: ?><span class="b b-warn">Необязательно</span><?php endif; ?>
          </td>
        </tr>
        <?php endforeach; ?>
      </table>
      <form method="post" class="actions">
        <input type="hidden" name="_csrf" value="<?= h($csrf) ?>">
        <input type="hidden" name="step" value="db-form">
        <button class="btn" <?= $envOk ? '' : 'disabled' ?>>Далее</button>
      </form>
      <?php if (!$envOk): ?><p class="muted">Исправьте пункты с пометкой «Ошибка» и обновите страницу.</p><?php endif; ?>

    <?php elseif ($step === 'db'): ?>
      <h1>Шаг 2 из 3 — база данных</h1>
      <form method="post">
        <input type="hidden" name="_csrf" value="<?= h($csrf) ?>">
        <input type="hidden" name="step" value="db-save">
        <div class="row">
          <div>
            <label>СУБД</label>
            <select name="db_driver">
              <option value="mysql" <?= $dbForm['driver'] === 'mysql' ? 'selected' : '' ?>>MySQL / MariaDB</option>
              <option value="pgsql" <?= $dbForm['driver'] === 'pgsql' ? 'selected' : '' ?>>PostgreSQL</option>
            </select>
          </div>
          <div>
            <label>Префикс таблиц</label>
            <input type="text" name="db_prefix" value="<?= h($dbForm['prefix']) ?>">
          </div>
        </div>
        <div class="row">
          <div>
            <label>Хост</label>
            <input type="text" name="db_host" value="<?= h($dbForm['host']) ?>">
          </div>
          <div>
            <label>Порт <span class="muted">(пусто = стандартный)</span></label>
            <input type="text" name="db_port" value="<?= h($dbForm['port']) ?>" placeholder="3306 / 5432">
          </div>
        </div>
        <label>Имя базы данных</label>
        <input type="text" name="db_name" value="<?= h($dbForm['name']) ?>" required>
        <div class="row">
          <div>
            <label>Пользователь</label>
            <input type="text" name="db_user" value="<?= h($dbForm['user']) ?>" required>
          </div>
          <div>
            <label>Пароль</label>
            <input type="password" name="db_pass" value="<?= h($dbForm['pass']) ?>">
          </div>
        </div>
        <div class="note">Если базы ещё нет, установщик попробует создать её сам (нужны права CREATE DATABASE у пользователя).</div>
        <div class="actions"><button class="btn">Проверить и продолжить</button></div>
      </form>

    <?php elseif ($step === 'admin'): ?>
      <h1>Шаг 3 из 3 — сайт и администратор</h1>
      <?php if (!empty($_SESSION['db_created'])): ?><div class="note">База данных создана автоматически.</div><?php endif; ?>
      <form method="post">
        <input type="hidden" name="_csrf" value="<?= h($csrf) ?>">
        <input type="hidden" name="step" value="run">
        <label>Название сайта</label>
        <input type="text" name="site_name" value="<?= h(post('site_name', 'Мой сайт')) ?>" required>
        <label>Адрес сайта (URL)</label>
        <input type="text" name="app_url" value="<?= h(post('app_url', $guessedUrl)) ?>" required>
        <label>E-mail администратора</label>
        <input type="email" name="admin_email" value="<?= h(post('admin_email')) ?>" required>
        <label>Имя администратора</label>
        <input type="text" name="admin_name" value="<?= h(post('admin_name', 'Администратор')) ?>">
        <div class="row">
          <div>
            <label>Пароль (мин. 8 символов)</label>
            <input type="password" name="admin_pass" minlength="8" required>
          </div>
          <div>
            <label>Пароль ещё раз</label>
            <input type="password" name="admin_pass2" minlength="8" required>
          </div>
        </div>
        <div class="actions"><button class="btn">Установить</button></div>
      </form>

    <?php elseif ($step === 'done'): ?>
      <h1>Установка завершена</h1>
      <ul class="log">
        <?php foreach ($installLog as $line): ?><li><?= h($line) ?></li><?php endforeach; ?>
        <li><?= $selfDeleted ? 'install.php удалён автоматически' : '<b>Удалите файл install.php вручную!</b>' ?></li>
      </ul>
      <div class="note">
        Вход в панель управления: <a href="/admin/login">/admin/login</a><br>
        Сайт: <a href="/">открыть главную</a>
      </div>
    <?php endif; ?>
  </div>
  <p class="muted" style="text-align:center; margin-top:14px">Celena CMS</p>
</div>
</body>
</html>
