<?php

require __DIR__ . '/../bootstrap.php';

use KeyLair\Auth;
use KeyLair\AuditLog;
use KeyLair\Csrf;
use KeyLair\Deployer;
use KeyLair\Helpers;
use KeyLair\I18n;
use KeyLair\Settings;

$admin = Auth::requireAdminTierView();
$isDemo = $admin['role'] === 'demo';

$flash = null;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if ($isDemo) {
        http_response_code(403);
        die(I18n::t('deploy.demo_readonly'));
    }
    Csrf::requireValid();
    $action = $_POST['form_action'] ?? '';

    if ($action === 'update') {
        $result = Deployer::pull();
        if ($result['ok']) {
            AuditLog::log($admin['id'], 'update_pulled', $result['output']);
            $flash = ['type' => 'success', 'message' => $result['output'] . ' ' . I18n::t('deploy.flash.check_migrations_suffix')];
        } else {
            $flash = ['type' => 'error', 'message' => I18n::t('deploy.flash.update_failed_prefix') . ' ' . $result['output']];
        }
    } elseif ($action === 'set_channel') {
        $channel = $_POST['channel'] ?? '';
        if (Settings::setUpdateChannel($channel)) {
            AuditLog::log($admin['id'], 'update_channel_changed', $channel);
            $flash = ['type' => 'success', 'message' => sprintf(I18n::t('deploy.flash.channel_changed'), $channel)];
        } else {
            $flash = ['type' => 'error', 'message' => I18n::t('deploy.flash.channel_unknown')];
        }
    }
}

$channelLabels = [
    'stable' => I18n::t('deploy.channel.stable'),
    'beta' => I18n::t('deploy.channel.beta'),
    'alpha' => I18n::t('deploy.channel.alpha'),
    'dev' => I18n::t('deploy.channel.dev'),
];

$hasZip = class_exists('ZipArchive');
$currentChannel = Settings::updateChannel();
$installedChannel = Settings::installedChannel();
$currentVersion = Deployer::currentVersion();

/**
 * The VERSION file itself is always a bare "X.Y.Z" -- a pre-release
 * build's git tag carries the "-dev"/"-alpha"/"-beta" suffix, but that
 * suffix never makes it into VERSION or the package coordinates (see
 * Deployer::channelTag()). Displayed alone, "0.6.10" next to Stable's
 * "0.6.7" reads as an arbitrary downgrade; reconstructing the suffix
 * from the channel it was actually installed/checked on makes it read
 * for what it is -- moving from a pre-release build to a stable one
 * (or vice versa), not a random version drop.
 */
$versionWithChannel = function (?string $version, ?string $channel) {
    if ($version === null) {
        return null;
    }
    return ($channel !== null && $channel !== 'stable') ? "{$version}-{$channel}" : $version;
};
$remoteVersion = $hasZip ? Deployer::remoteVersion() : null;
$updateAvailable = $remoteVersion !== null && $remoteVersion !== $currentVersion;

// installedChannel only otherwise updates on an actual Deployer::pull() --
// if switching channels lands on one whose latest is already what's
// installed (no update needed), there's no pull to attach that channel to,
// so the badge below would keep showing whatever channel the last real
// update came from instead of the one just confirmed to match.
if (!$updateAvailable && $remoteVersion !== null && $installedChannel !== $currentChannel) {
    Settings::setInstalledChannel($currentChannel);
    $installedChannel = $currentChannel;
}

$currentChangelogHtml = null;
$currentHistory = Helpers::changelogAll(Deployer::localChangelog());
if ($currentHistory !== null) {
    $currentChangelogHtml = Helpers::renderChangelogHtml($currentHistory);
}

// Every version strictly newer than what's installed, combined -- an
// update always jumps straight to the latest build, so this is what you'd
// actually receive, not just the newest version's own changes.
$remoteChangelogHtml = null;
if ($updateAvailable) {
    $remoteRange = Helpers::changelogSince(Deployer::remoteChangelog(), $currentVersion);
    if ($remoteRange !== null) {
        $remoteChangelogHtml = Helpers::renderChangelogHtml($remoteRange);
    }
}

$pageTitle = I18n::t('deploy.page_title');
$activeNav = 'deploy';
$extraAdminCss = 'admin-product-editor';
require __DIR__ . '/includes/layout_header.php';
?>
<div class="topbar"><h1><?= Helpers::e(I18n::t('deploy.page_title')) ?></h1></div>

<?php if ($flash): ?>
  <div class="panel" style="border-color:<?= $flash['type'] === 'success' ? 'var(--signal-dim)' : 'var(--danger)' ?>; margin-bottom:16px;">
    <pre style="color:<?= $flash['type'] === 'success' ? 'var(--signal)' : 'var(--danger)' ?>; font-size:12.5px; white-space:pre-wrap; margin:0; font-family:var(--font-mono);"><?= Helpers::e($flash['message']) ?></pre>
  </div>
<?php endif; ?>

<div class="panel" style="margin-bottom:16px; <?= $currentChannel !== 'stable' ? 'border-color:var(--key-gold);' : '' ?>">
  <p class="panel-title"><?= Helpers::e(I18n::t('deploy.channel_panel_title')) ?></p>
  <p style="color:var(--text-muted); font-size:13px; max-width:640px; margin:0 0 14px;">
    <?= I18n::t('deploy.channel_explanation_html') ?>
  </p>
  <form method="post" style="display:flex; gap:10px; align-items:center; flex-wrap:wrap;">
    <?= Csrf::field() ?>
    <input type="hidden" name="form_action" value="set_channel">
    <select name="channel" onchange="this.form.submit()" <?= $isDemo ? 'disabled' : '' ?> style="background:var(--bg-void); border:1px solid var(--line); color:var(--text-primary); padding:8px 10px; border-radius:var(--radius-sm); font-size:13px;">
      <option value="stable" <?= $currentChannel === 'stable' ? 'selected' : '' ?>><?= Helpers::e($channelLabels['stable']) ?></option>
      <option value="beta" <?= $currentChannel === 'beta' ? 'selected' : '' ?>><?= Helpers::e($channelLabels['beta']) ?></option>
      <option value="alpha" <?= $currentChannel === 'alpha' ? 'selected' : '' ?>><?= Helpers::e($channelLabels['alpha']) ?></option>
      <option value="dev" <?= $currentChannel === 'dev' ? 'selected' : '' ?>><?= Helpers::e($channelLabels['dev']) ?></option>
    </select>
    <?php if ($currentChannel !== 'stable'): ?>
      <span class="status-pill" style="background:rgba(232,181,99,0.14); color:var(--key-gold);"><?= Helpers::e(I18n::t('deploy.channel_tracking_badge')) ?></span>
    <?php endif; ?>
  </form>
</div>

<?php if (!$hasZip): ?>
  <div class="panel" style="margin-bottom:16px;">
    <p class="panel-title"><?= Helpers::e(I18n::t('deploy.zip_missing_title')) ?></p>
    <p style="color:var(--text-muted); font-size:13px;">
      <?= I18n::t('deploy.zip_missing_text_html') ?>
    </p>
  </div>
<?php endif; ?>

<div class="panel">
  <p class="panel-title"><?= Helpers::e(I18n::t('deploy.version_panel_title')) ?></p>
  <div class="version-row" style="display:flex; align-items:center; gap:24px; flex-wrap:wrap; margin-bottom:<?= $updateAvailable ? '16px' : '0' ?>;">
    <div class="version-current" style="min-width:0; flex:1 1 auto;">
      <p style="font-size:11px; color:var(--text-faint); text-transform:uppercase; letter-spacing:0.06em; margin:0 0 4px;">
        <?= Helpers::e(I18n::t('deploy.current_label')) ?><?php if ($installedChannel !== null && $installedChannel !== 'stable'): ?> &middot; <?= Helpers::e($channelLabels[$installedChannel]) ?><?php endif; ?>
      </p>
      <p style="font-family:var(--font-mono); font-size:18px; margin:0;"><?= Helpers::e($versionWithChannel($currentVersion, $installedChannel) ?? I18n::t('deploy.version_unknown')) ?></p>
      <?php if ($currentChangelogHtml !== null): ?>
      <details style="margin-top:6px;">
        <summary style="color:var(--text-muted); font-size:12px; cursor:pointer;"><?= Helpers::e(I18n::t('deploy.full_changelog')) ?></summary>
        <div style="margin-top:8px; max-width:100%; max-height:400px; overflow-y:auto; overflow-wrap:break-word; font-size:13px; line-height:1.5; color:var(--text-muted);"><?= $currentChangelogHtml ?></div>
      </details>
      <?php endif; ?>
    </div>
    <?php if ($updateAvailable): ?>
      <svg class="version-arrow" viewBox="0 0 24 24" fill="none" stroke="var(--text-faint)" stroke-width="2" style="width:20px; height:20px;"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
      <div class="version-available" style="min-width:0; flex:1 1 auto;">
        <p style="font-size:11px; color:var(--key-gold); text-transform:uppercase; letter-spacing:0.06em; margin:0 0 4px;">
          <?= Helpers::e(I18n::t('deploy.available_label')) ?><?php if ($currentChannel !== 'stable'): ?> &middot; <?= Helpers::e($channelLabels[$currentChannel]) ?><?php endif; ?>
        </p>
        <p style="font-family:var(--font-mono); font-size:18px; color:var(--key-gold); margin:0;"><?= Helpers::e($versionWithChannel($remoteVersion, $currentChannel)) ?></p>
        <?php if ($remoteChangelogHtml !== null): ?>
        <details style="margin-top:6px;">
          <summary style="color:var(--text-muted); font-size:12px; cursor:pointer;"><?= Helpers::e(I18n::t('deploy.update_preview_summary')) ?></summary>
          <div style="margin-top:8px; max-width:100%; max-height:400px; overflow-y:auto; overflow-wrap:break-word; font-size:13px; line-height:1.5; color:var(--text-muted);"><?= $remoteChangelogHtml ?></div>
        </details>
        <?php endif; ?>
      </div>
    <?php endif; ?>
  </div>

  <?php if (!$hasZip): ?>
    <p style="color:var(--text-muted); font-size:13px;"><?= I18n::t('deploy.zip_required_notice_html') ?></p>
  <?php elseif ($updateAvailable && $isDemo): ?>
    <button type="button" id="update-now-btn" class="btn btn-primary" disabled><?= Helpers::e(sprintf(I18n::t('deploy.update_to_button'), $versionWithChannel($remoteVersion, $currentChannel))) ?></button>
  <?php elseif ($updateAvailable): ?>
    <form method="post" id="update-form">
      <?= Csrf::field() ?>
      <input type="hidden" name="form_action" value="update">
      <button type="button" id="update-now-btn" class="btn btn-primary" onclick="document.getElementById('update-confirm-dialog').showModal()"><?= Helpers::e(sprintf(I18n::t('deploy.update_to_button'), $versionWithChannel($remoteVersion, $currentChannel))) ?></button>
    </form>
    <dialog id="update-confirm-dialog" style="border:1px solid var(--line); border-radius:var(--radius-md); background:var(--bg-panel); color:var(--text-primary); padding:20px; max-width:400px;">
      <p style="margin:0 0 16px; font-size:13.5px; line-height:1.5;"><?= Helpers::e(I18n::t('deploy.update_confirm_dialog_text')) ?></p>
      <div style="display:flex; gap:10px; justify-content:flex-end;">
        <button type="button" class="btn btn-ghost" onclick="document.getElementById('update-confirm-dialog').close()"><?= Helpers::e(I18n::t('deploy.cancel_button')) ?></button>
        <button type="submit" form="update-form" class="btn btn-primary"><?= Helpers::e(I18n::t('deploy.confirm_update_button')) ?></button>
      </div>
    </dialog>
    <style>dialog::backdrop{background:rgba(0,0,0,0.55);}</style>
  <?php elseif ($remoteVersion === null): ?>
    <p style="color:var(--text-muted); font-size:13px;"><?= Helpers::e(I18n::t('deploy.remote_unreachable')) ?></p>
  <?php else: ?>
    <p style="color:var(--text-muted); font-size:13px;"><?= Helpers::e(I18n::t('deploy.up_to_date')) ?></p>
  <?php endif; ?>
</div>

<?php require __DIR__ . '/includes/layout_footer.php'; ?>
