<?php
/**
 * Bakit Storage — Self-bootstrapping installer for shared hosting.
 *
 * Upload ONLY this file to your web root, visit it in a browser.
 * It downloads the storage-api into a /bakit subfolder, sets up the database,
 * and generates your API token.
 *
 * Result:  webroot/bakit/  (all Bakit files)
 *          webroot/.htaccess  (routes /api/v1/* into bakit/)
 */

if (php_sapi_name() === 'cli') {
    die("This installer must be run in a web browser.\n");
}

$basePath = dirname(__FILE__);
$bakitPath = $basePath . '/bakit';

// Reset: ?reset=1 removes existing install so you can reinstall
if (isset($_GET['reset']) && $_GET['reset'] === '1' && is_dir($bakitPath)) {
    // Recursively delete /bakit directory
    $it = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($bakitPath, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    foreach ($it as $f) {
        $f->isDir() ? @rmdir($f->getPathname()) : @unlink($f->getPathname());
    }
    @rmdir($bakitPath);

    // Remove Bakit block from .htaccess
    $htaccess = $basePath . '/.htaccess';
    if (file_exists($htaccess)) {
        $content = file_get_contents($htaccess);
        $cleaned = preg_replace('/# --- BEGIN BAKIT ---.*?# --- END BAKIT ---\n?/s', '', $content);
        $cleaned = trim($cleaned);
        if ($cleaned === '') {
            @unlink($htaccess);
        } else {
            file_put_contents($htaccess, $cleaned . "\n");
        }
    }

    header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
    exit;
}

$alreadyInstalled = is_dir($bakitPath) && file_exists($bakitPath . '/.env');
$step = $_POST['step'] ?? 'form';
$errors = [];
$result = null;

$repoOwner = 'marekpilar';
$repoName = 'bakit';

// Discover latest version from version.json
$versionInfo = null;
$versionJsonUrl = 'https://bakit.online/releases/version.json';
$versionJsonRaw = @file_get_contents($versionJsonUrl, false, stream_context_create([
    'http' => ['timeout' => 10, 'header' => "User-Agent: Bakit-Installer\r\n"],
]));
if ($versionJsonRaw !== false) {
    $versionInfo = json_decode($versionJsonRaw, true);
}
$latestVersion = $versionInfo['latest'] ?? '1.3.0';
$version = $_POST['version'] ?? "v{$latestVersion}";

if ($step === 'install' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $dbDriver = $_POST['db_driver'] ?? 'sqlite';
    $dbHost = trim($_POST['db_host'] ?? '');
    $dbPort = trim($_POST['db_port'] ?? '3306');
    $dbName = trim($_POST['db_name'] ?? '');
    $dbUser = trim($_POST['db_user'] ?? '');
    $dbPass = $_POST['db_pass'] ?? '';

    if ($dbDriver === 'mysql') {
        if ($dbHost === '') $errors[] = 'MySQL host is required.';
        if ($dbName === '') $errors[] = 'Database name is required.';
        if ($dbUser === '') $errors[] = 'Username is required.';
    }

    // --- Phase 1: Download & extract into /bakit ---
    if (empty($errors) && !is_dir($bakitPath . '/src')) {
        // Prefer dedicated storage tarball, fall back to full tarball
        $storageUrl = $versionInfo['storage_url'] ?? null;
        $urls = array_filter([
            $storageUrl,
            "https://bakit.online/releases/{$version}.tar.gz",
            "https://github.com/{$repoOwner}/{$repoName}/archive/refs/tags/{$version}.tar.gz",
        ]);
        $expectedSha256 = $versionInfo['storage_sha256'] ?? ($versionInfo['sha256'] ?? null);
        $isStorageTarball = !empty($storageUrl);

        $archivePath = $basePath . '/bakit-download.tar.gz';
        $downloaded = false;
        $lastError = '';

        foreach ($urls as $url) {
            if (function_exists('curl_init')) {
                $ch = curl_init($url);
                $fp = fopen($archivePath, 'w');
                curl_setopt_array($ch, [
                    CURLOPT_FILE => $fp,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_TIMEOUT => 120,
                    CURLOPT_USERAGENT => 'Bakit-Installer/1.0',
                ]);
                curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                curl_close($ch);
                fclose($fp);

                if ($httpCode >= 200 && $httpCode < 400 && filesize($archivePath) > 1000) {
                    $downloaded = true;
                    break;
                }
                $lastError = "HTTP {$httpCode} from {$url}";
                @unlink($archivePath);
            } elseif (ini_get('allow_url_fopen')) {
                $ctx = stream_context_create(['http' => [
                    'header' => "User-Agent: Bakit-Installer/1.0\r\n",
                    'timeout' => 120,
                    'follow_location' => true,
                ]]);
                $data = @file_get_contents($url, false, $ctx);
                if ($data !== false && strlen($data) > 1000) {
                    file_put_contents($archivePath, $data);
                    $downloaded = true;
                    break;
                }
                $lastError = "Failed to fetch {$url}";
            }
        }

        if (!$downloaded) {
            $errors[] = "Failed to download Bakit. {$lastError}";
        }

        // Extract
        if ($downloaded && empty($errors)) {
            $extractDir = $basePath . '/bakit-extract-tmp';
            @mkdir($extractDir, 0755, true);

            $extracted = false;
            if (class_exists('PharData')) {
                try {
                    $phar = new PharData($archivePath);
                    $phar->decompress();
                    $tarFile = preg_replace('/\.gz$/i', '', $archivePath);
                    if (file_exists($tarFile)) {
                        $tar = new PharData($tarFile);
                        $tar->extractTo($extractDir);
                        @unlink($tarFile);
                        $extracted = true;
                    }
                } catch (Exception $e) {
                    $lastError = $e->getMessage();
                }
            }

            if (!$extracted && function_exists('shell_exec')) {
                @shell_exec(sprintf('tar -xzf %s -C %s 2>&1', escapeshellarg($archivePath), escapeshellarg($extractDir)));
                if (is_dir($extractDir) && count(@scandir($extractDir)) > 2) {
                    $extracted = true;
                }
            }

            if (!$extracted) {
                $errors[] = "Failed to extract archive. Error: {$lastError}";
            }

            @unlink($archivePath);

            if ($extracted && empty($errors)) {
                // Find storage-api in extracted archive
                $found = glob($extractDir . '/*/storage-api') ?: glob($extractDir . '/storage-api') ?: [];

                if (!empty($found)) {
                    $sourceDir = $found[0];
                    @mkdir($bakitPath, 0755, true);

                    // Copy storage-api contents into /bakit
                    $iterator = new RecursiveIteratorIterator(
                        new RecursiveDirectoryIterator($sourceDir, RecursiveDirectoryIterator::SKIP_DOTS),
                        RecursiveIteratorIterator::SELF_FIRST
                    );
                    foreach ($iterator as $item) {
                        $target = $bakitPath . '/' . $iterator->getSubPathname();
                        if ($item->isDir()) {
                            @mkdir($target, 0755, true);
                        } else {
                            @copy($item->getPathname(), $target);
                        }
                    }
                } else {
                    $errors[] = 'Could not find storage-api directory in archive.';
                }

                // Cleanup extract dir
                $it = new RecursiveIteratorIterator(
                    new RecursiveDirectoryIterator($extractDir, RecursiveDirectoryIterator::SKIP_DOTS),
                    RecursiveIteratorIterator::CHILD_FIRST
                );
                foreach ($it as $f) {
                    $f->isDir() ? @rmdir($f->getPathname()) : @unlink($f->getPathname());
                }
                @rmdir($extractDir);
            }
        }
    }

    // --- Phase 2: Database + config ---
    if (empty($errors)) {
        try {
            if ($dbDriver === 'sqlite') {
                $dbPath = $bakitPath . '/storage/database.sqlite';
                @mkdir(dirname($dbPath), 0755, true);
                $pdo = new PDO("sqlite:{$dbPath}", null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
                $pdo->exec('PRAGMA foreign_keys = ON');
                $pdo->exec('PRAGMA journal_mode = WAL');

                $pdo->exec("CREATE TABLE IF NOT EXISTS api_tokens (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, token_hash TEXT NOT NULL UNIQUE, is_active INTEGER NOT NULL DEFAULT 1, expires_at TEXT NULL, last_used_at TEXT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')))");
                $pdo->exec("CREATE TABLE IF NOT EXISTS backups (id INTEGER PRIMARY KEY AUTOINCREMENT, external_id TEXT NOT NULL, site_domain TEXT NOT NULL, backup_type TEXT NOT NULL, filename TEXT NOT NULL, total_size_bytes INTEGER NOT NULL DEFAULT 0, size_bytes INTEGER NULL, chunk_count INTEGER NOT NULL DEFAULT 1, checksum TEXT NOT NULL, is_complete INTEGER NOT NULL DEFAULT 0, storage_path TEXT NULL, notes TEXT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')))");
                $pdo->exec("CREATE TABLE IF NOT EXISTS chunks (id INTEGER PRIMARY KEY AUTOINCREMENT, backup_id INTEGER NOT NULL, chunk_index INTEGER NOT NULL, size_bytes INTEGER NOT NULL DEFAULT 0, checksum TEXT NOT NULL, stored_path TEXT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')), UNIQUE (backup_id, chunk_index), FOREIGN KEY (backup_id) REFERENCES backups(id) ON DELETE CASCADE)");

                $envContent = "DB_DRIVER=sqlite\nAPP_DEBUG=false\n";
            } else {
                $dsn = sprintf('mysql:host=%s;port=%d;charset=utf8mb4', $dbHost, (int)$dbPort);
                $pdo = new PDO($dsn, $dbUser, $dbPass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
                $pdo->exec("CREATE DATABASE IF NOT EXISTS `{$dbName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
                $pdo->exec("USE `{$dbName}`");

                $pdo->exec("CREATE TABLE IF NOT EXISTS api_tokens (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, token_hash VARCHAR(64) NOT NULL UNIQUE, is_active TINYINT(1) NOT NULL DEFAULT 1, expires_at DATETIME NULL, last_used_at DATETIME NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_token_hash (token_hash)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
                $pdo->exec("CREATE TABLE IF NOT EXISTS backups (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, external_id VARCHAR(255) NOT NULL, site_domain VARCHAR(255) NOT NULL, backup_type VARCHAR(50) NOT NULL, filename VARCHAR(500) NOT NULL, total_size_bytes BIGINT UNSIGNED NOT NULL DEFAULT 0, size_bytes BIGINT UNSIGNED NULL, chunk_count INT UNSIGNED NOT NULL DEFAULT 1, checksum VARCHAR(64) NOT NULL, is_complete TINYINT(1) NOT NULL DEFAULT 0, storage_path TEXT NULL, notes TEXT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_site_domain (site_domain), INDEX idx_is_complete (is_complete), INDEX idx_external_id (external_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
                $pdo->exec("CREATE TABLE IF NOT EXISTS chunks (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, backup_id INT UNSIGNED NOT NULL, chunk_index INT UNSIGNED NOT NULL, size_bytes BIGINT UNSIGNED NOT NULL DEFAULT 0, checksum VARCHAR(64) NOT NULL, stored_path TEXT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_backup_chunk (backup_id, chunk_index), CONSTRAINT fk_chunks_backup FOREIGN KEY (backup_id) REFERENCES backups(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");

                $envContent = "DB_DRIVER=mysql\nDB_HOST={$dbHost}\nDB_PORT={$dbPort}\nDB_DATABASE={$dbName}\nDB_USERNAME={$dbUser}\nDB_PASSWORD={$dbPass}\nAPP_DEBUG=false\n";
            }

            // Generate API token (skip if one already exists)
            $existingTokens = (int) $pdo->query('SELECT COUNT(*) FROM api_tokens WHERE is_active = 1')->fetchColumn();
            if ($existingTokens > 0) {
                $plainToken = null;
            } else {
                $plainToken = bin2hex(random_bytes(32));
                $tokenHash = hash('sha256', $plainToken);
                $now = gmdate('Y-m-d H:i:s');
                $stmt = $pdo->prepare('INSERT INTO api_tokens (name, token_hash, is_active, created_at, updated_at) VALUES (?, ?, 1, ?, ?)');
                $stmt->execute(['Bakit Server', $tokenHash, $now, $now]);
            }

            // Write .env inside bakit/
            file_put_contents($bakitPath . '/.env', $envContent);

            // Create storage directories
            @mkdir($bakitPath . '/storage/backups', 0755, true);
            @mkdir($bakitPath . '/storage/chunks', 0755, true);
            @mkdir($bakitPath . '/storage/logs', 0755, true);

            // Create root .htaccess — routes /api/v1/* to bakit/public/index.php
            $htaccess = $basePath . '/.htaccess';
            $htaccessContent = <<<'HTACCESS'
# --- BEGIN BAKIT ---
<IfModule mod_rewrite.c>
    RewriteEngine On

    # Pass Authorization header to PHP (Apache/CGI strips it)
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Existing files/dirs in web root — serve directly
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ - [L]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # Route /api/v1/* to Bakit storage API
    RewriteRule ^api/v1/(.*)$ bakit/public/index.php [QSA,L]
</IfModule>

<IfModule mod_setenvif.c>
    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
</IfModule>
# --- END BAKIT ---
HTACCESS;
            // Write or update .htaccess — use markers to avoid duplicates
            if (!file_exists($htaccess)) {
                file_put_contents($htaccess, $htaccessContent);
            } else {
                $existing = file_get_contents($htaccess);
                // Remove old Bakit block if present, then re-add
                $cleaned = preg_replace('/# --- BEGIN BAKIT ---.*?# --- END BAKIT ---\n?/s', '', $existing);
                file_put_contents($htaccess, trim($cleaned) . "\n\n" . $htaccessContent);
            }

            // Self-delete
            $selfDelete = !empty($_POST['self_delete']);
            if ($selfDelete) {
                @unlink(__FILE__);
            }

            $apiBase = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/api/v1';

            $result = [
                'token' => $plainToken,
                'existing_tokens' => $existingTokens ?? 0,
                'self_deleted' => $selfDelete,
                'api_url' => $apiBase,
            ];

        } catch (PDOException $e) {
            $errors[] = 'Database error: ' . $e->getMessage();
        }
    }

    if (!empty($errors)) {
        $step = 'form';
    }
}

?><!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bakit Storage Installer</title>
    <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #f1f5f9; color: #1e293b; line-height: 1.5; padding: 2rem 1rem; }
        .container { max-width: 560px; margin: 0 auto; }
        .card { background: #fff; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,.1); padding: 2rem; margin-bottom: 1.5rem; }
        h1 { font-size: 1.5rem; margin-bottom: .25rem; }
        .subtitle { color: #64748b; margin-bottom: 1.5rem; }
        label { display: block; font-weight: 600; margin-bottom: .25rem; margin-top: 1rem; font-size: .9rem; }
        label:first-of-type { margin-top: 0; }
        input[type="text"], input[type="password"], input[type="number"] { width: 100%; padding: .5rem .75rem; border: 1px solid #cbd5e1; border-radius: 6px; font-size: .95rem; }
        input:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,.15); }
        .row { display: flex; gap: 1rem; }
        .row > div { flex: 1; }
        button { margin-top: 1.5rem; width: 100%; padding: .65rem; background: #3b82f6; color: #fff; border: none; border-radius: 6px; font-size: 1rem; font-weight: 600; cursor: pointer; }
        button:hover { background: #2563eb; }
        .errors { background: #fef2f2; border: 1px solid #fecaca; color: #b91c1c; padding: .75rem 1rem; border-radius: 6px; margin-bottom: 1rem; }
        .errors li { margin-left: 1rem; }
        .token-box { background: #f0fdf4; border: 1px solid #bbf7d0; padding: 1rem; border-radius: 6px; margin: 1rem 0; word-break: break-all; font-family: monospace; font-size: .85rem; }
        .info-box { background: #eff6ff; border: 1px solid #bfdbfe; padding: 1rem; border-radius: 6px; margin: 1rem 0; }
        .info-box code { background: #dbeafe; padding: .15rem .4rem; border-radius: 3px; font-size: .85rem; }
        .warning { background: #fffbeb; border: 1px solid #fde68a; color: #92400e; padding: .75rem 1rem; border-radius: 6px; margin-top: 1rem; font-weight: 600; }
        .success-icon { color: #16a34a; font-size: 2.5rem; margin-bottom: .5rem; }
        .checkbox-row { display: flex; align-items: center; gap: .5rem; margin-top: 1.25rem; }
        .checkbox-row input { width: auto; }
        .checkbox-row label { margin: 0; font-weight: 400; }
        .muted { color: #64748b; font-size: .85rem; }
        .steps { display: flex; gap: .5rem; margin-bottom: 1.5rem; }
        .steps .step { flex: 1; text-align: center; padding: .4rem; background: #e2e8f0; border-radius: 4px; font-size: .8rem; color: #64748b; }
        .steps .step.active { background: #3b82f6; color: #fff; }
        .steps .step.done { background: #22c55e; color: #fff; }
    </style>
</head>
<body>
<div class="container">

<?php if ($result !== null): ?>
    <div class="card" style="text-align:center;">
        <div class="steps">
            <div class="step done">Download</div>
            <div class="step done">Database</div>
            <div class="step done">Complete</div>
        </div>

        <div class="success-icon">&#10003;</div>
        <h1>Bakit Storage Ready</h1>
        <p class="subtitle">The storage API is installed and ready to receive backups.</p>

        <div style="text-align:left;">
            <div class="info-box">
                <strong>API Base URL:</strong><br>
                <code><?php echo htmlspecialchars($result['api_url']); ?></code>
            </div>

            <?php if ($result['token'] !== null): ?>
                <label>API Token (one-time display):</label>
                <div class="token-box"><?php echo htmlspecialchars($result['token']); ?></div>
                <p class="muted">Copy this token now. It cannot be retrieved later.</p>
                <p class="muted" style="margin-top:.5rem;">Enter this token in your Bakit Server when adding a "Bakit Storage" destination.</p>
            <?php else: ?>
                <div class="info-box">
                    <strong>An API token already exists.</strong><br>
                    Use the token from your first installation. No new token was created.
                </div>
            <?php endif; ?>
        </div>

        <?php if ($result['self_deleted']): ?>
            <div class="warning">This installer file has been automatically deleted.</div>
        <?php else: ?>
            <div class="warning" style="background: #fef2f2; border-color: #fecaca; color: #b91c1c;">WARNING: The installer file is still accessible. Anyone can re-run it and create new API tokens. Delete it immediately.</div>
        <?php endif; ?>
    </div>

<?php elseif ($alreadyInstalled): ?>
    <div class="card">
        <div class="steps">
            <div class="step done">Configure</div>
            <div class="step done">Download</div>
            <div class="step done">Complete</div>
        </div>

        <h1>Bakit Storage Already Installed</h1>
        <p class="subtitle">A Bakit installation was detected in the <code>/bakit</code> directory.</p>

        <div class="warning" style="background: #fef2f2; border-color: #fecaca; color: #b91c1c;">WARNING: This installer file is still accessible. Anyone can re-run it and create new API tokens. Delete it immediately.</div>
        <p class="muted" style="margin-top:1rem; text-align:center;">Delete <strong><?php echo htmlspecialchars(basename(__FILE__)); ?></strong> from your server to prevent unauthorized access.</p>

        <div style="margin-top:1.5rem; padding-top:1.5rem; border-top:1px solid #e2e8f0; text-align:center;">
            <p class="muted" style="margin-bottom:.5rem;">Need to reinstall? This will delete all data and backups.</p>
            <a href="?reset=1" onclick="return confirm('This will permanently delete all backups and the database. Continue?')" style="color: #b91c1c; font-weight:600; font-size:.9rem;">Reset &amp; Reinstall</a>
        </div>
    </div>

<?php else:
    // --- Preflight checks ---
    $preflight = [];
    $preflightOk = true;

    // PHP version
    if (version_compare(PHP_VERSION, '8.0.0', '>=')) {
        $preflight[] = ['ok', 'PHP ' . PHP_VERSION];
    } else {
        $preflight[] = ['fail', 'PHP ' . PHP_VERSION . ' — requires 8.0+'];
        $preflightOk = false;
    }

    // PDO available
    if (extension_loaded('pdo')) {
        $preflight[] = ['ok', 'PDO extension'];
    } else {
        $preflight[] = ['fail', 'PDO extension missing — required for database'];
        $preflightOk = false;
    }

    // Download capability
    if (function_exists('curl_init')) {
        $preflight[] = ['ok', 'cURL available'];
    } elseif (ini_get('allow_url_fopen')) {
        $preflight[] = ['warn', 'Using allow_url_fopen (cURL preferred)'];
    } else {
        $preflight[] = ['fail', 'Cannot download files — enable cURL or allow_url_fopen'];
        $preflightOk = false;
    }

    // Archive extraction
    if (class_exists('PharData')) {
        $preflight[] = ['ok', 'PharData available'];
    } elseif (function_exists('shell_exec')) {
        $preflight[] = ['warn', 'Using shell tar (PharData preferred)'];
    } else {
        $preflight[] = ['fail', 'Cannot extract archives — enable PharData or shell_exec'];
        $preflightOk = false;
    }

    // Web root writable
    if (is_writable($basePath)) {
        $preflight[] = ['ok', 'Web root writable'];
    } else {
        $preflight[] = ['fail', 'Web root is not writable — check file permissions'];
        $preflightOk = false;
    }

    // Disk space (disk_free_space may be disabled on shared hosting)
    $freeBytes = function_exists('disk_free_space') ? @disk_free_space($basePath) : false;
    if ($freeBytes !== false) {
        $freeMb = round($freeBytes / 1048576);
        if ($freeBytes < 52428800) { // < 50 MB
            $preflight[] = ['fail', "{$freeMb} MB free — need at least 50 MB"];
            $preflightOk = false;
        } elseif ($freeBytes < 524288000) { // < 500 MB
            $preflight[] = ['warn', "{$freeMb} MB free — may fill up quickly with backups"];
        } else {
            $preflight[] = ['ok', "{$freeMb} MB free"];
        }
    }

    // .htaccess support (check for mod_rewrite)
    if (function_exists('apache_get_modules') && in_array('mod_rewrite', apache_get_modules())) {
        $preflight[] = ['ok', 'mod_rewrite available'];
    } else {
        $preflight[] = ['warn', 'Cannot verify mod_rewrite — API routing may not work if Apache'];
    }
?>
    <div class="card">
        <div class="steps">
            <div class="step active">Configure</div>
            <div class="step">Download</div>
            <div class="step">Complete</div>
        </div>

        <h1>Bakit Storage Installer</h1>
        <p class="subtitle">This will download the Bakit Storage API into a <code>/bakit</code> subfolder and configure the database.</p>

        <div style="margin-bottom:1.25rem; padding:.75rem 1rem; background:#f8fafc; border:1px solid #e2e8f0; border-radius:6px; font-size:.85rem;">
            <strong style="font-size:.9rem;">System Check</strong>
            <?php foreach ($preflight as [$level, $msg]): ?>
                <div style="margin-top:.35rem;">
                    <?php if ($level === 'ok'): ?>
                        <span style="color:#16a34a;">&#10003;</span>
                    <?php elseif ($level === 'warn'): ?>
                        <span style="color:#d97706;">!</span>
                    <?php else: ?>
                        <span style="color:#dc2626;">&#10007;</span>
                    <?php endif; ?>
                    <?php echo htmlspecialchars($msg); ?>
                </div>
            <?php endforeach; ?>
        </div>

        <?php if (!$preflightOk): ?>
            <div class="errors">
                <strong>Cannot install.</strong> Fix the issues above and reload this page.
            </div>
        <?php endif; ?>

        <?php if (!empty($errors)): ?>
            <div class="errors">
                <ul>
                <?php foreach ($errors as $e): ?>
                    <li><?php echo htmlspecialchars($e); ?></li>
                <?php endforeach; ?>
                </ul>
            </div>
        <?php endif; ?>

        <form method="POST" id="installForm">
            <input type="hidden" name="step" value="install">
            <input type="hidden" name="version" value="<?php echo htmlspecialchars($version); ?>">

            <label style="margin-top:0;">Database</label>
            <div class="row" style="margin-bottom:.5rem;">
                <div>
                    <label style="margin-top:.25rem;"><input type="radio" name="db_driver" value="sqlite" checked onchange="document.getElementById('mysql-fields').style.display='none'"> SQLite <span style="font-weight:400;color:#64748b">(recommended — no setup needed)</span></label>
                </div>
                <div>
                    <label style="margin-top:.25rem;"><input type="radio" name="db_driver" value="mysql" onchange="document.getElementById('mysql-fields').style.display='block'"> MySQL</label>
                </div>
            </div>

            <div id="mysql-fields" style="display:none;">
                <div class="row">
                    <div>
                        <label for="db_host">MySQL Host</label>
                        <input type="text" id="db_host" name="db_host" value="<?php echo htmlspecialchars($_POST['db_host'] ?? 'localhost'); ?>">
                    </div>
                    <div style="max-width:120px;">
                        <label for="db_port">Port</label>
                        <input type="number" id="db_port" name="db_port" value="<?php echo htmlspecialchars($_POST['db_port'] ?? '3306'); ?>">
                    </div>
                </div>

                <label for="db_name">Database Name</label>
                <input type="text" id="db_name" name="db_name" value="<?php echo htmlspecialchars($_POST['db_name'] ?? 'bakit_storage'); ?>">

                <label for="db_user">Username</label>
                <input type="text" id="db_user" name="db_user" value="<?php echo htmlspecialchars($_POST['db_user'] ?? ''); ?>">

                <label for="db_pass">Password</label>
                <input type="password" id="db_pass" name="db_pass" value="">
            </div>

            <div class="checkbox-row">
                <input type="checkbox" id="self_delete" name="self_delete" value="1" checked>
                <label for="self_delete">Delete this installer after setup</label>
            </div>

            <button type="submit"<?php if (!$preflightOk) echo ' disabled style="opacity:.5;cursor:not-allowed;"'; ?>>Install Bakit Storage</button>
            <p class="muted" style="margin-top:.75rem; text-align:center;">Downloads ~1.2MB, installs into /bakit. SQLite needs no external database.</p>
        </form>
    </div>
<?php endif; ?>

</div>
</body>
</html>
