<?php
/**
 * setup.php – OSCE Nexus™ first-run installer.
 *
 * Walks through:
 *   1) Welcome + requirements check
 *   2) Database configuration  → writes .osce_env
 *   3) Schema installation     → runs migrations/fresh_install.sql
 *   4) Create first super-admin
 *   5) Done
 *
 * After installation, this script self-locks by checking that .osce_env exists,
 * an admin user exists, and tables are populated – then redirects to login.
 */

require_once __DIR__ . '/env_loader.php';
osce_load_env();

// Use a separate session name so wizard state doesn't bleed into the app session.
if (session_status() === PHP_SESSION_NONE) {
    session_set_cookie_params([
        'lifetime' => 0, 'path' => '/', 'httponly' => true, 'samesite' => 'Lax',
    ]);
    session_name('OSCESETUP');
    session_start();
}

// Self-lock: if env is present and admin exists, refuse to run again
function setup_is_complete(): bool
{
    if (!osce_env_present()) return false;
    $host = osce_env('DB_HOST', 'localhost');
    $name = osce_env('DB_NAME', '');
    $user = osce_env('DB_USER', '');
    $pass = osce_env('DB_PASS', '');
    if (!$name || !$user) return false;
    try {
        $pdo = new PDO("mysql:host=$host;dbname=$name;charset=utf8mb4", $user, $pass,
                      [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
        $stmt = $pdo->query("SELECT COUNT(*) c FROM users WHERE role='super_admin' AND active=1");
        return (int)$stmt->fetch(PDO::FETCH_ASSOC)['c'] > 0;
    } catch (Throwable $e) {
        return false;
    }
}

if (isset($_GET['force'])) {
    // explicit re-install request – clear wizard session
    $_SESSION = [];
}

$isComplete = setup_is_complete();
$showingDoneStep = (int)($_GET['step'] ?? 0) === 5 && !empty($_SESSION['setup_admin_ready']);
if ($isComplete && !isset($_GET['force']) && !$showingDoneStep) {
    // already installed
    header('Location: login.php');
    exit;
}

// ---------- CSRF ----------
if (empty($_SESSION['setup_csrf'])) {
    $_SESSION['setup_csrf'] = bin2hex(random_bytes(32));
}
function setup_csrf_field(): string
{
    return '<input type="hidden" name="_csrf" value="' . htmlspecialchars($_SESSION['setup_csrf'] ?? '', ENT_QUOTES) . '">';
}
function setup_csrf_ok(): bool
{
    return !empty($_SESSION['setup_csrf']) && hash_equals($_SESSION['setup_csrf'], (string)($_POST['_csrf'] ?? ''));
}

// ---------- Step routing ----------
$step = (int)($_GET['step'] ?? ($_POST['step'] ?? 1));
if ($step < 1 || $step > 5) $step = 1;

$errors = [];
$notice = '';

// helpers ---------------------------------------------------------------
function reqs_check(): array
{
    $rows = [];
    $ok = true;

    $phpOk = version_compare(PHP_VERSION, '7.4.0', '>=');
    $rows[] = ['PHP version (≥ 7.4)', PHP_VERSION, $phpOk];
    $ok = $ok && $phpOk;

    foreach (['pdo_mysql','json','mbstring','session'] as $ext) {
        $loaded = extension_loaded($ext);
        $rows[] = ["PHP extension: $ext", $loaded ? 'loaded' : 'MISSING', $loaded];
        $ok = $ok && $loaded;
    }

    $write = osce_env_pick_write_path();
    $rows[] = ['Writable location for .osce_env', $write ?: 'none found', (bool)$write];
    $ok = $ok && (bool)$write;

    $appDirWrite = is_writable(__DIR__);
    $rows[] = ['App directory writable (for migrations)', __DIR__, $appDirWrite];
    // not strictly required, just informational
    return [$ok, $rows];
}

function db_try_connect(string $host, string $name, string $user, string $pass): array
{
    try {
        $dsn = "mysql:host=$host;dbname=$name;charset=utf8mb4";
        $pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
        return [true, $pdo, ''];
    } catch (Throwable $e) {
        return [false, null, $e->getMessage()];
    }
}

function db_try_create(string $host, string $name, string $user, string $pass): array
{
    // Connect without DB, attempt to CREATE DATABASE
    try {
        $pdo = new PDO("mysql:host=$host;charset=utf8mb4", $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
        $pdo->exec("CREATE DATABASE IF NOT EXISTS `" . str_replace('`','',$name) . "` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci");
        return [true, ''];
    } catch (Throwable $e) {
        return [false, $e->getMessage()];
    }
}

function write_env_file(array $vars): array
{
    $path = osce_env_pick_write_path();
    if (!$path) return [false, 'No writable location found for .osce_env.', null];

    $body = "# OSCE Nexus environment – generated by setup wizard\n";
    $body .= "# Created " . date('c') . "\n\n";
    foreach ($vars as $k => $v) {
        // escape simple cases – wrap in double quotes
        $vEsc = str_replace(['\\', '"'], ['\\\\', '\\"'], (string)$v);
        $body .= sprintf("%s=\"%s\"\n", $k, $vEsc);
    }

    $ok = @file_put_contents($path, $body) !== false;
    if ($ok) @chmod($path, 0600);
    return [$ok, $ok ? '' : 'Could not write env file.', $path];
}

function run_sql_file(PDO $pdo, string $path): array
{
    $sql = file_get_contents($path);
    if ($sql === false) return [false, "Could not read $path"];

    // Naive but safe-enough splitter that respects PREPARE/EXECUTE blocks by
    // executing the whole file as one multi-statement batch via PDO::exec.
    try {
        $pdo->exec($sql);
        return [true, ''];
    } catch (Throwable $e) {
        return [false, $e->getMessage()];
    }
}

// ---------- Step handlers ----------

// STEP 2 -> POST -> save DB
if ($_SERVER['REQUEST_METHOD'] === 'POST' && (int)($_POST['step'] ?? 0) === 2) {
    if (!setup_csrf_ok()) {
        $errors[] = 'CSRF check failed. Reload and try again.';
    } else {
        $host = trim((string)($_POST['db_host'] ?? 'localhost'));
        $name = trim((string)($_POST['db_name'] ?? ''));
        $user = trim((string)($_POST['db_user'] ?? ''));
        $pass = (string)($_POST['db_pass'] ?? '');
        $createDb = isset($_POST['create_db']);

        if ($name === '' || $user === '') {
            $errors[] = 'Database name and user are required.';
        } else {
            if ($createDb) {
                [$ok, $err] = db_try_create($host, $name, $user, $pass);
                if (!$ok) $errors[] = 'Could not create database: ' . $err;
            }

            if (!$errors) {
                [$ok, $pdo, $err] = db_try_connect($host, $name, $user, $pass);
                if (!$ok) {
                    $errors[] = 'Connection failed: ' . $err;
                } else {
                    // success - save .osce_env
                    [$wrote, $werr, $path] = write_env_file([
                        'APP_ENV'              => 'local',
                        'APP_DEBUG'            => '0',
                        'APP_KEY'              => bin2hex(random_bytes(32)),
                        'DB_HOST'              => $host,
                        'DB_NAME'              => $name,
                        'DB_USER'              => $user,
                        'DB_PASS'              => $pass,
                        'SESSION_SECURE'       => '0',           // local dev is HTTP
                        'SESSION_SAMESITE'     => 'Lax',
                        'LOGIN_MAX_ATTEMPTS'   => '5',
                        'LOGIN_LOCKOUT_MINUTES'=> '15',
                        'PASSWORD_MIN_LENGTH'  => '10',
                    ]);
                    if (!$wrote) {
                        $errors[] = $werr;
                    } else {
                        $_SESSION['setup_env_path'] = $path;
                        $_SESSION['setup_db_ready'] = true;
                        header('Location: setup.php?step=3');
                        exit;
                    }
                }
            }
        }
    }
    $step = 2;
}

// STEP 3 -> POST -> run schema
if ($_SERVER['REQUEST_METHOD'] === 'POST' && (int)($_POST['step'] ?? 0) === 3) {
    if (!setup_csrf_ok()) {
        $errors[] = 'CSRF check failed.';
    } else {
        // reload env we just wrote
        osce_load_env(); // cached – force re-read by clearing cache via path argument
        // env loader caches; bypass:
        osce_load_env($_SESSION['setup_env_path'] ?? null);

        $host = osce_env('DB_HOST', 'localhost');
        $name = osce_env('DB_NAME', '');
        $user = osce_env('DB_USER', '');
        $pass = osce_env('DB_PASS', '');

        [$ok, $pdo, $err] = db_try_connect($host, $name, $user, $pass);
        if (!$ok) {
            $errors[] = 'Cannot reconnect to DB: ' . $err;
        } else {
            $schemaFile = __DIR__ . '/migrations/fresh_install.sql';
            if (!is_readable($schemaFile)) {
                $errors[] = "Schema file missing: $schemaFile";
            } else {
                [$ok, $err] = run_sql_file($pdo, $schemaFile);
                if (!$ok) {
                    $errors[] = 'Schema install error: ' . $err;
                } else {
                    $_SESSION['setup_schema_ready'] = true;
                    header('Location: setup.php?step=4');
                    exit;
                }
            }
        }
    }
    $step = 3;
}

// STEP 4 -> POST -> create admin
if ($_SERVER['REQUEST_METHOD'] === 'POST' && (int)($_POST['step'] ?? 0) === 4) {
    if (!setup_csrf_ok()) {
        $errors[] = 'CSRF check failed.';
    } else {
        $username  = trim((string)($_POST['username']  ?? ''));
        $full_name = trim((string)($_POST['full_name'] ?? ''));
        $password  = (string)($_POST['password']  ?? '');
        $password2 = (string)($_POST['password2'] ?? '');

        if (!preg_match('/^[A-Za-z0-9._-]{3,50}$/', $username)) $errors[] = 'Username must be 3–50 chars (letters/digits/._-)';
        if ($full_name === '') $errors[] = 'Full name is required.';
        if (strlen($password) < 10)            $errors[] = 'Password must be at least 10 characters.';
        if (!preg_match('/[A-Z]/', $password)) $errors[] = 'Password must contain an uppercase letter.';
        if (!preg_match('/[a-z]/', $password)) $errors[] = 'Password must contain a lowercase letter.';
        if (!preg_match('/\d/',    $password)) $errors[] = 'Password must contain a digit.';
        if ($password !== $password2)          $errors[] = 'Passwords do not match.';

        if (!$errors) {
            osce_load_env($_SESSION['setup_env_path'] ?? null);
            [$ok, $pdo, $err] = db_try_connect(
                osce_env('DB_HOST','localhost'),
                osce_env('DB_NAME',''),
                osce_env('DB_USER',''),
                osce_env('DB_PASS','')
            );
            if (!$ok) {
                $errors[] = 'DB connect error: ' . $err;
            } else {
                try {
                    $hash = password_hash($password, PASSWORD_DEFAULT);
                    $stmt = $pdo->prepare("
                        INSERT INTO users (username, password_hash, full_name, role, facility_id, active)
                        VALUES (?, ?, ?, 'super_admin', NULL, 1)
                    ");
                    $stmt->execute([$username, $hash, $full_name]);
                    $_SESSION['setup_admin_ready'] = true;
                    header('Location: setup.php?step=5');
                    exit;
                } catch (Throwable $e) {
                    if (str_contains($e->getMessage(), 'Duplicate')) {
                        $errors[] = 'A user with that username already exists.';
                    } else {
                        $errors[] = 'Could not create admin: ' . $e->getMessage();
                    }
                }
            }
        }
    }
    $step = 4;
}

// reqs check happens inline on step 1
[$reqsOk, $reqsRows] = reqs_check();

?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OSCE Nexus™ – Setup</title>
<link rel="stylesheet" href="assets/css/app.css">
<style>
.wizard { max-width: 760px; margin: 24px auto; padding: 16px; }
.steps { display: flex; gap: 6px; margin-bottom: 18px; flex-wrap: wrap; }
.steps .pill { padding: 8px 14px; border-radius: 999px; background: #e2e8f0; color: #475569; font-size: 13px; font-weight: 600; }
.steps .pill.active { background: var(--c-primary); color: #fff; }
.steps .pill.done   { background: var(--c-success); color: #fff; }
.req-table td.ok    { color: var(--c-success); font-weight: 700; }
.req-table td.bad   { color: var(--c-danger);  font-weight: 700; }
.code-block { background: #0f172a; color: #f1f5f9; padding: 10px 14px; border-radius: 6px; font-size: 13px; }
</style>
</head>
<body>

<div class="topbar">
    <div class="brand">OSCE Nexus™ <small>Setup Wizard</small></div>
</div>

<div class="wizard">
    <div class="container">
        <div class="steps">
            <?php
            $labels = [1=>'Welcome',2=>'Database',3=>'Schema',4=>'Admin user',5=>'Done'];
            foreach ($labels as $n => $lbl):
                $cls = $n === $step ? 'active' : ($n < $step ? 'done' : '');
            ?>
                <span class="pill <?php echo $cls; ?>"><?php echo $n . '. ' . htmlspecialchars($lbl, ENT_QUOTES); ?></span>
            <?php endforeach; ?>
        </div>

        <?php if ($errors): ?>
            <div class="alert alert-danger">
                <ul style="margin:0; padding-left:18px;">
                    <?php foreach ($errors as $e): ?><li><?php echo htmlspecialchars($e, ENT_QUOTES); ?></li><?php endforeach; ?>
                </ul>
            </div>
        <?php endif; ?>

        <?php /* ==================== STEP 1: WELCOME / REQS ==================== */ ?>
        <?php if ($step === 1): ?>
            <h2>Welcome</h2>
            <p>This wizard will:</p>
            <ol>
                <li>Check your server meets requirements.</li>
                <li>Save your database settings to <code>.osce_env</code> (kept outside the webroot).</li>
                <li>Install the database schema.</li>
                <li>Create your first super-admin account.</li>
            </ol>

            <h3>Requirements check</h3>
            <div class="table-wrap">
            <table class="data req-table">
                <thead><tr><th>Check</th><th>Result</th><th>Status</th></tr></thead>
                <tbody>
                <?php foreach ($reqsRows as $r): ?>
                    <tr>
                        <td><?php echo htmlspecialchars($r[0], ENT_QUOTES); ?></td>
                        <td><code><?php echo htmlspecialchars((string)$r[1], ENT_QUOTES); ?></code></td>
                        <td class="<?php echo $r[2] ? 'ok' : 'bad'; ?>"><?php echo $r[2] ? '✓ OK' : '✗ FAIL'; ?></td>
                    </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
            </div>

            <?php if ($reqsOk): ?>
                <p class="mt-2">
                    <a href="setup.php?step=2" class="btn btn-primary btn-lg">Continue →</a>
                </p>
            <?php else: ?>
                <div class="alert alert-warning mt-2">
                    Fix the failing checks above, then reload this page.
                </div>
            <?php endif; ?>

        <?php /* ==================== STEP 2: DATABASE ==================== */ ?>
        <?php elseif ($step === 2): ?>
            <h2>Database configuration</h2>
            <p>Enter your MySQL/MariaDB connection details. On XAMPP the defaults below usually work; on shared hosting use your cPanel-issued credentials.</p>

            <form method="post" action="setup.php?step=2">
                <?php echo setup_csrf_field(); ?>
                <input type="hidden" name="step" value="2">
                <div class="form-row">
                    <div class="field"><label>Host</label><input type="text" name="db_host" value="<?php echo htmlspecialchars($_POST['db_host'] ?? 'localhost', ENT_QUOTES); ?>" required></div>
                    <div class="field"><label>Database name</label><input type="text" name="db_name" value="<?php echo htmlspecialchars($_POST['db_name'] ?? 'osce_nexus', ENT_QUOTES); ?>" required></div>
                </div>
                <div class="form-row">
                    <div class="field"><label>User</label><input type="text" name="db_user" value="<?php echo htmlspecialchars($_POST['db_user'] ?? 'root', ENT_QUOTES); ?>" required></div>
                    <div class="field"><label>Password</label><input type="password" name="db_pass" value="<?php echo htmlspecialchars($_POST['db_pass'] ?? '', ENT_QUOTES); ?>"></div>
                </div>
                <p>
                    <label><input type="checkbox" name="create_db" value="1" <?php echo isset($_POST['create_db']) ? 'checked' : 'checked'; ?>>
                        Create the database if it doesn't exist
                    </label>
                </p>
                <p>
                    <button type="submit" class="btn btn-primary btn-lg">Test connection &amp; save</button>
                </p>
            </form>

        <?php /* ==================== STEP 3: SCHEMA ==================== */ ?>
        <?php elseif ($step === 3): ?>
            <h2>Install schema</h2>
            <?php if (empty($_SESSION['setup_db_ready'])): ?>
                <div class="alert alert-danger">You haven't finished step 2. <a href="setup.php?step=2">Go back.</a></div>
            <?php else: ?>
                <p>We'll run <code>migrations/fresh_install.sql</code> against your database. This creates all the tables and seeds one default facility.</p>
                <form method="post" action="setup.php?step=3">
                    <?php echo setup_csrf_field(); ?>
                    <input type="hidden" name="step" value="3">
                    <button type="submit" class="btn btn-primary btn-lg">Install schema now</button>
                </form>
            <?php endif; ?>

        <?php /* ==================== STEP 4: ADMIN ==================== */ ?>
        <?php elseif ($step === 4): ?>
            <h2>Create your super-admin account</h2>
            <?php if (empty($_SESSION['setup_schema_ready'])): ?>
                <div class="alert alert-danger">Schema not installed yet. <a href="setup.php?step=3">Go back.</a></div>
            <?php else: ?>
                <p>This is the account you'll use to log in for the first time. Make the password strong – we enforce: ≥ 10 chars with uppercase, lowercase, and a digit.</p>
                <form method="post" action="setup.php?step=4">
                    <?php echo setup_csrf_field(); ?>
                    <input type="hidden" name="step" value="4">
                    <div class="form-row">
                        <div class="field"><label>Username</label><input type="text" name="username" value="<?php echo htmlspecialchars($_POST['username'] ?? 'admin', ENT_QUOTES); ?>" required></div>
                        <div class="field"><label>Full name</label><input type="text" name="full_name" value="<?php echo htmlspecialchars($_POST['full_name'] ?? '', ENT_QUOTES); ?>" required></div>
                    </div>
                    <div class="form-row">
                        <div class="field"><label>Password</label><input type="password" name="password" required autocomplete="new-password"></div>
                        <div class="field"><label>Confirm password</label><input type="password" name="password2" required autocomplete="new-password"></div>
                    </div>
                    <button type="submit" class="btn btn-primary btn-lg">Create admin &amp; finish</button>
                </form>
            <?php endif; ?>

        <?php /* ==================== STEP 5: DONE ==================== */ ?>
        <?php elseif ($step === 5): ?>
            <?php if (empty($_SESSION['setup_admin_ready'])): ?>
                <div class="alert alert-danger">Admin not yet created. <a href="setup.php?step=4">Go back.</a></div>
            <?php else: ?>
                <h2>✅ Installation complete</h2>
                <p>OSCE Nexus™ v2 is ready. Your environment file was written to:</p>
                <p class="code-block"><?php echo htmlspecialchars($_SESSION['setup_env_path'] ?? '?', ENT_QUOTES); ?></p>
                <p>What to do next:</p>
                <ol>
                    <li><a href="login.php" class="btn btn-primary">Sign in</a> with the admin account you just created.</li>
                    <li>From there: add facilities, examiners, candidates, and forms.</li>
                    <li>For production: review the recommendations in <code>DEPLOYMENT.md</code>.</li>
                </ol>
                <p class="muted">Note: the wizard self-locks now. To re-run it, delete the env file shown above and load <code>setup.php?force=1</code>.</p>
                <?php $_SESSION = []; ?>
            <?php endif; ?>
        <?php endif; ?>
    </div>
</div>

<small class="copyright">
    &copy; <?php echo date('Y'); ?> Khalaf Almazrouei – OSCE Nexus™.
</small>
</body>
</html>
