<?php
/**
 * BROWSER-ONLY INSTALLER (v2) — no SSH / Terminal required.
 *
 * FIX vs v1: Composer and Laravel are now run in SEPARATE HTTP requests
 * (separate PHP processes). Running Composer's internals and then booting
 * Laravel in the SAME process can leave old Composer-bundled classes
 * (e.g. an older Symfony\Component\Console\Application) loaded in memory,
 * which Laravel's own code then tries to use instead of your project's
 * real vendor/symfony/console — causing errors like
 * "Call to undefined method Symfony\Component\Console\Application::addCommand()".
 * Splitting into two requests guarantees a clean slate for Laravel.
 *
 * HOW TO USE:
 *   1. Upload into the SAME folder as composer.json / artisan.
 *   2. Edit INSTALL_TOKEN below.
 *   3. Visit: https://your-domain/install-web.php?token=YOUR_TOKEN
 *   4. Fill the form -> Step 1 runs Composer -> click "Continue" ->
 *      Step 2 (fresh request) writes .env, runs key:generate, migrate,
 *      storage:link.
 *   5. DELETE THIS FILE + composer.phar when finished.
 */

const INSTALL_TOKEN = '123';

set_time_limit(0);
ignore_user_abort(true);
error_reporting(E_ALL);
ini_set('display_errors', '1');

$root = __DIR__;

function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES); }
function out($msg, $ok = true) {
    $color = $ok ? '#0a7d2c' : '#b3261e';
    echo "<div style='padding:4px 0;color:$color;font-family:monospace;white-space:pre-wrap'>" . h($msg) . "</div>";
    if (ob_get_level() > 0) { @ob_flush(); }
    @flush();
}
function fail($msg) { out("FATAL: $msg", false); echo "</div></body></html>"; exit; }

$token = $_GET['token'] ?? $_POST['token'] ?? '';
if (INSTALL_TOKEN === 'CHANGE-ME-TO-SOMETHING-ONLY-YOU-KNOW') {
    fail('Edit INSTALL_TOKEN in this file to a real secret before using it.');
}
if (!hash_equals(INSTALL_TOKEN, $token)) {
    http_response_code(403);
    fail('Invalid or missing token. Visit as: install-web.php?token=YOUR_TOKEN');
}

$step = $_GET['step'] ?? $_POST['step'] ?? '1';

?><!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>UAE Transport Accounting — Web Installer</title>
<style>
  body{font-family:-apple-system,Segoe UI,Arial,sans-serif;max-width:820px;margin:30px auto;padding:0 16px;background:#0e1116;color:#e6e6e6}
  h1{font-size:20px} h2{font-size:16px;margin-top:28px;border-bottom:1px solid #333;padding-bottom:6px}
  label{display:block;margin:12px 0 4px;font-size:13px;color:#bbb}
  input[type=text],input[type=password]{width:100%;padding:8px;border-radius:6px;border:1px solid #444;background:#1a1e24;color:#eee;box-sizing:border-box}
  button,.btn{margin-top:18px;padding:10px 18px;border:0;border-radius:6px;background:#3d7dfc;color:#fff;font-size:14px;cursor:pointer;text-decoration:none;display:inline-block}
  .log{background:#000;border-radius:6px;padding:12px;margin-top:16px;max-height:480px;overflow:auto}
  .warn{background:#332400;border:1px solid #665000;padding:10px;border-radius:6px;margin-top:16px;font-size:13px}
</style>
</head>
<body>
<h1>UAE Transport Accounting — Web Installer</h1>

<?php

// =====================================================================
// STEP 1 form (initial page load)
// =====================================================================
if ($step === '1' && empty($_POST['submitted'])):
?>
<div class="warn">Delete this file from the server once installation finishes.</div>
<h2>Step 1 — Enter your details</h2>
<form method="post">
  <input type="hidden" name="token" value="<?= h($token) ?>">
  <input type="hidden" name="step" value="1">
  <input type="hidden" name="submitted" value="1">
  <label>APP_URL</label>
  <input type="text" name="app_url" required value="https://<?= h($_SERVER['HTTP_HOST'] ?? 'yourdomain.com') ?>">
  <label>DB_DATABASE</label>
  <input type="text" name="db_database" required>
  <label>DB_USERNAME</label>
  <input type="text" name="db_username" required>
  <label>DB_PASSWORD</label>
  <input type="password" name="db_password" required>
  <button type="submit">Run Composer install</button>
</form>
<?php
    exit;
endif;

// =====================================================================
// STEP 1 processing: write .env + run composer install
// =====================================================================
if ($step === '1' && !empty($_POST['submitted'])):
    echo "<h2>Step 1 — Installing dependencies</h2><div class='log'>";

    $appUrl = trim($_POST['app_url'] ?? '');
    $dbName = trim($_POST['db_database'] ?? '');
    $dbUser = trim($_POST['db_username'] ?? '');
    $dbPass = (string)($_POST['db_password'] ?? '');

    if ($appUrl === '' || $dbName === '' || $dbUser === '') {
        fail('All fields are required.');
    }
    if (!extension_loaded('phar')) {
        fail('The PHP "phar" extension is not enabled. Ask your host to enable it.');
    }
    if (!file_exists("$root/composer.json")) {
        fail("composer.json not found in $root.");
    }

    // --- write .env FIRST (doesn't need Laravel booted) ---
    out('Writing .env ...');
    $envPath = "$root/.env";
    if (!file_exists($envPath)) {
        if (!file_exists("$root/.env.example")) fail('.env.example not found.');
        copy("$root/.env.example", $envPath);
    }
    $env = file_get_contents($envPath);
    function setEnvValue(string $env, string $key, string $value): string {
        $escaped = addcslashes($value, '"\\');
        $needsQuotes = preg_match('/\s/', $value) || $value === '';
        $line = $needsQuotes ? "{$key}=\"{$escaped}\"" : "{$key}={$value}";
        return preg_match("/^{$key}=.*/m", $env)
            ? preg_replace("/^{$key}=.*/m", $line, $env)
            : rtrim($env) . "\n{$line}\n";
    }
    $env = setEnvValue($env, 'APP_URL', $appUrl);
    $env = setEnvValue($env, 'APP_ENV', 'production');
    $env = setEnvValue($env, 'APP_DEBUG', 'false');
    $env = setEnvValue($env, 'DB_DATABASE', $dbName);
    $env = setEnvValue($env, 'DB_USERNAME', $dbUser);
    $env = setEnvValue($env, 'DB_PASSWORD', $dbPass);
    $env = setEnvValue($env, 'SESSION_SECURE_COOKIE', 'true');
    file_put_contents($envPath, $env);
    out('.env written.');

    // --- download composer.phar if needed ---
    $composerPhar = "$root/composer.phar";
    if (!file_exists($composerPhar)) {
        out('Downloading composer.phar ...');
        $data = @file_get_contents('https://getcomposer.org/composer.phar');
        if ($data === false && function_exists('curl_init')) {
            $ch = curl_init('https://getcomposer.org/composer.phar');
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, 120);
            $data = curl_exec($ch);
            curl_close($ch);
        }
        if (!$data) fail('Could not download composer.phar — host may block outbound HTTPS from PHP.');
        file_put_contents($composerPhar, $data);
        out('composer.phar downloaded.');
    } else {
        out('composer.phar already present.');
    }

    // --- run composer install in-process ---
    out('Running composer install --no-dev --optimize-autoloader ...');
    chdir($root);
    putenv('COMPOSER_HOME=' . $root . '/.composer-home');
    @mkdir($root . '/.composer-home', 0775, true);

    try {
        require_once 'phar://' . $composerPhar . '/src/bootstrap.php';
        $input = new Symfony\Component\Console\Input\ArrayInput([
            'command' => 'install',
            '--no-dev' => true,
            '--optimize-autoloader' => true,
            '--no-interaction' => true,
            '--no-progress' => true,
            '-d' => $root,
        ]);
        $output = new Symfony\Component\Console\Output\BufferedOutput();
        $application = new Composer\Console\Application();
        $application->setAutoExit(false);
        $exitCode = $application->run($input, $output);
        out($output->fetch());
        if ($exitCode !== 0) fail("composer install exited with code $exitCode.");
        out('Composer dependencies installed successfully.');
    } catch (\Throwable $e) {
        fail('Composer install failed: ' . $e->getMessage());
    }

    if (!file_exists("$root/vendor/autoload.php")) {
        fail('vendor/autoload.php still missing after composer install.');
    }

    echo "</div>";
    ?>
    <h2>Step 1 complete</h2>
    <p>Composer finished successfully in this request. Click below to continue in a
       <strong>fresh page load</strong> — this avoids a known class-collision issue
       between Composer's internals and Laravel's own dependencies.</p>
    <a class="btn" href="?token=<?= h($token) ?>&step=2">Continue to Step 2 &rarr;</a>
    <?php
    exit;
endif;

// =====================================================================
// STEP 2: fresh request — boot Laravel, run artisan commands
// =====================================================================
if ($step === '2'):
    echo "<h2>Step 2 — Laravel setup</h2><div class='log'>";

    if (!file_exists("$root/vendor/autoload.php")) {
        fail('vendor/autoload.php not found — go back and complete Step 1 first.');
    }
    if (!file_exists("$root/.env")) {
        fail('.env not found — go back and complete Step 1 first.');
    }

    // fix permissions before booting
    out('Fixing storage/ and bootstrap/cache/ permissions ...');
    foreach ([
        "$root/storage/app/private", "$root/storage/app/public",
        "$root/storage/framework/cache/data", "$root/storage/framework/sessions",
        "$root/storage/framework/views", "$root/storage/logs", "$root/bootstrap/cache",
    ] as $d) {
        if (!is_dir($d)) @mkdir($d, 0775, true);
        @chmod($d, 0775);
    }
    out('Permissions set.');

    try {
        require "$root/vendor/autoload.php";
        $app = require "$root/bootstrap/app.php";

        // Mimic the real `artisan` CLI entrypoint exactly (kernel->handle),
        // rather than the Artisan facade, for maximum compatibility.
        $kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);

        $runArtisan = function (array $argv) use ($kernel) {
            $input = new Symfony\Component\Console\Input\ArgvInput(array_merge(['artisan'], $argv));
            $output = new Symfony\Component\Console\Output\BufferedOutput();
            $status = $kernel->handle($input, $output);
            out($output->fetch());
            return $status;
        };

        out('Running key:generate ...');
        $s1 = $runArtisan(['key:generate', '--force']);
        if ($s1 !== 0) fail('key:generate failed (exit code ' . $s1 . ').');

        out('Running migrate ...');
        $s2 = $runArtisan(['migrate', '--force']);
        if ($s2 !== 0) fail('migrate failed (exit code ' . $s2 . ') — check DB_DATABASE/DB_USERNAME/DB_PASSWORD in .env and that the DB user has privileges on that database.');

        out('Running storage:link ...');
        $runArtisan(['storage:link']);

        out('Laravel setup complete.');
    } catch (\Throwable $e) {
        fail('Laravel bootstrap/artisan step failed: ' . $e->getMessage());
    }

    echo "</div>";
    $appUrlGuess = 'https://' . ($_SERVER['HTTP_HOST'] ?? 'yourdomain.com');
    ?>
    <h2>Next steps</h2>
    <ol>
      <li><strong>Delete install-web.php and composer.phar from the server now.</strong></li>
      <li>In cPanel &raquo; Domains, set this domain's Document Root to:<br>
          <code><?= h($root) ?>/public</code></li>
      <li>Visit <code><?= h($appUrlGuess) ?>/install</code> to finish company/admin setup.</li>
    </ol>
    <?php
    exit;
endif;

fail('Unknown step.');