<%- include("partials/layout-top", { title, pageWidth: "wide", pageId: "update-management" }) %>
<%
  const status = updateStatus || {};
  const core = status.core || null;
  const plugins = status.plugins || [];
  const summary = status.plugins_summary || { installed_plugins: 0, total_plugins: 0, updatable_plugins: 0, blocked_plugins: 0 };
  const recovery = recoveryStatus || status.recovery || {};
  const marker = recovery.marker || null;
  const selectedSource = status.requested_source || "stable";
  const badgeClass = (item) => item?.blocked ? "danger" : item?.update_available ? "warning" : "success";
  const badgeText = (item) => item?.blocked ? "Blocked" : item?.update_available ? "Update available" : "Current";
  const toolBadgeClass = (item) => item?.blocked ? "danger" : item?.update_available || item?.installed === false ? "warning" : "success";
  const toolBadgeText = (item) => item?.blocked ? "Blocked" : item?.installed === false ? "Available" : item?.update_available ? "Update available" : "Current";
  const changelogItems = (item) => Array.isArray(item?.changelog_range) ? item.changelog_range : [];
  const applyLabel = (item) => item?.unversioned_update ? "Review and continue" : item?.installed === false ? "Install plugin" : "Apply update";
  const applyConfirmText = (item, label) => {
    const base = `${label}: create a backup, prepare recovery, apply ${item?.safe_target_version || "the selected update"}, and verify before finishing.`;
    if (!item?.unversioned_update) return base;
    const warnings = (item.warnings || []).join(" ");
    return `${base} Warning: this update is to or from an unversioned install or update, so Lumi cannot fully verify version order, changelog range, or restore safety. ${warnings}`;
  };
  const retention = snapshotRetention || { max_age_days: 30, max_per_target: 5 };
  const deployment = typeof deploymentState !== "undefined" && deploymentState ? deploymentState : { branch: "main", commit: null, version: core?.current_version || "unknown", previous_branch: null };
  const deployableBranches = typeof deploymentBranches !== "undefined" && Array.isArray(deploymentBranches) ? deploymentBranches : [];
  const deploymentIssue = typeof deploymentError !== "undefined" ? deploymentError : null;
  const deploymentSnapshot = (snapshots || [])
    .filter((snapshot) => snapshot.type === "bot" && snapshot.status === "available")
    .sort((left, right) => Number(right.createdAt || 0) - Number(left.createdAt || 0))[0] || null;
  const shortCommit = (value) => value ? String(value).slice(0, 10) : "Not recorded";
  const formatBytes = (value) => {
    const bytes = Number(value) || 0;
    if (bytes < 1024) return `${bytes} B`;
    const units = ["KB", "MB", "GB", "TB"];
    let size = bytes;
    let unit = -1;
    do { size /= 1024; unit += 1; } while (size >= 1024 && unit < units.length - 1);
    return `${size >= 10 ? size.toFixed(0) : size.toFixed(1)} ${units[unit]}`;
  };
%>

<div data-update-management data-update-source="<%= selectedSource %>">

<section class="card">
  <%- include("partials/page-header", {
    eyebrow: "Maintenance",
    pageTitle: "Updates",
    description: "Repository-first core and plugin updates with backups, recovery markers, restore actions, and advanced ZIP fallback."
  }) %>
  <% if (updateStatusError) { %>
  <div class="callout danger">Update metadata could not be loaded: <%= updateStatusError %></div>
  <% } %>
  <form method="get" action="/admin/updates" class="inline-actions" data-update-source-form>
    <label class="field compact">
      <span>Update source</span>
      <select name="source">
        <option value="stable" <%= selectedSource === "stable" ? "selected" : "" %>>Stable</option>
        <option value="experimental" <%= selectedSource === "experimental" ? "selected" : "" %>>Experimental</option>
      </select>
    </label>
    <button class="button subtle" type="submit">Reload metadata</button>
  </form>
  <p class="hint">Stable checks read repo metadata from <code>main</code>. Experimental branches are considered only when selected here.</p>
  <div class="callout info">
    <strong>Your local data stays in place</strong>
    <p>Updates preserve settings, databases, feedback and attachments, plugin data, AI models and runtimes, exports, community knowledge, corrections, and locally owned knowledge files. Lumi creates a backup first and automatically tries to restore it if an update fails.</p>
  </div>
</section>

<div class="update-notice-stack" data-update-notices aria-live="polite" aria-label="Update notifications"></div>

<section class="card" data-deployment-panel>
  <div class="section-header">
    <div>
      <span class="eyebrow">Production deployment</span>
      <h2>Running code branch</h2>
      <p class="hint">Safely test an experimental branch, return to stable <code>main</code>, or repair the currently selected branch, including bundled plugin code.</p>
    </div>
    <span class="badge <%= deployment.branch === "main" ? "success" : "warning" %>"><%= deployment.branch === "main" ? "Stable" : "Experimental" %></span>
  </div>

  <div class="update-meta-grid">
    <div><span>Running branch</span><strong><%= deployment.branch %></strong></div>
    <div><span>Running commit</span><strong><%= shortCommit(deployment.commit) %></strong></div>
    <div><span>Core version</span><strong><%= deployment.version || core?.current_version || "unknown" %></strong></div>
    <div><span>Previous branch</span><strong><%= deployment.previous_branch || "Not recorded" %></strong></div>
  </div>

  <div class="callout info">
    <strong>Safe switch sequence</strong>
    <p>Lumi fetches and verifies the exact branch, backs up core and bundled-plugin code plus the database, preserves every plugin data directory and local-only plugin, applies the branch, then gracefully restarts. If applying the branch fails, Lumi automatically restores the backup.</p>
  </div>

  <% if (deploymentIssue) { %>
  <div class="callout warning"><strong>Branch list unavailable</strong><p><%= deploymentIssue %> Existing update and recovery controls remain available.</p></div>
  <% } %>

  <% if (deployableBranches.length) { %>
  <form method="post" action="/admin/updates/core/deploy-branch" class="input-action-row" data-update-action data-confirm-mode="modal" data-confirm-title="Switch Lumi production branch" data-confirm-text="Verify and deploy core plus bundled-plugin code from the selected branch after creating a rollback snapshot, then gracefully restart Lumi. Local data, plugin data, and local-only plugins stay in place." data-confirm-label="Deploy branch">
    <label class="field">
      <span>Branch to run</span>
      <select name="branch" required>
        <% deployableBranches.forEach((branch) => { %>
        <option value="<%= branch.name %>" <%= branch.name === deployment.branch ? "selected" : "" %>><%= branch.name === "main" ? "Stable · main" : `Experimental · ${branch.name}` %><%= branch.commit ? ` · ${shortCommit(branch.commit)}` : "" %><%= branch.unavailable ? " · no longer listed remotely" : "" %></option>
        <% }) %>
      </select>
    </label>
    <button class="button" type="submit">Deploy selected branch</button>
  </form>
  <p class="hint">Selecting the running branch performs a verified repair deployment. Branches are limited to <code>main</code> and published <code>experimental-*</code> branches.</p>
  <% } %>

  <div class="inline-actions">
    <% if (deployment.branch !== "main" && deployableBranches.some((branch) => branch.name === "main")) { %>
    <form method="post" action="/admin/updates/core/deploy-branch" data-update-action data-confirm-mode="modal" data-confirm-title="Return production to stable main" data-confirm-text="Back up the running experimental code, deploy the current main branch while preserving live data, verify it, and gracefully restart Lumi." data-confirm-label="Return to main">
      <input type="hidden" name="branch" value="main" />
      <button class="button" type="submit">Return safely to main</button>
    </form>
    <% } %>
    <% if (deploymentSnapshot) { %>
    <form method="post" action="/admin/updates/core/revert" data-update-action data-confirm-mode="modal" data-confirm-title="Restore emergency deployment backup" data-confirm-text="Restore the previous core code and its database backup, then restart Lumi. Changes written to the database after that backup may be lost; prefer Return safely to main when Lumi is still working." data-confirm-label="Restore backup">
      <input type="hidden" name="source" value="<%= selectedSource %>" />
      <input type="hidden" name="snapshot_id" value="<%= deploymentSnapshot.id %>" />
      <button class="button danger" type="submit">Emergency restore previous backup</button>
    </form>
    <% } %>
  </div>
</section>

<div data-update-recovery-region>
<% if (recovery.has_incomplete_marker || marker) { %>
<section class="card update-recovery-banner">
  <h2>Safe Mode / Recovery</h2>
  <p>
    Recovery marker status:
    <strong><%= marker?.status || "none" %></strong>
    <% if (marker?.target_kind) { %>
    for <strong><%= marker.target_kind %><%= marker.target_id ? `:${marker.target_id}` : "" %></strong>
    <% } %>
  </p>
  <% if (marker) { %>
  <div class="update-meta-grid">
    <div><span>From</span><strong><%= marker.from_version || "unknown" %></strong></div>
    <div><span>To</span><strong><%= marker.to_version || "unknown" %></strong></div>
    <div><span>Method</span><strong><%= marker.update_method || "unknown" %></strong></div>
    <div><span>Source</span><strong><%= marker.source_branch || "unknown" %></strong></div>
    <div><span>Snapshot</span><strong><%= marker.snapshot_id || "pending" %></strong></div>
    <div><span>Updated</span><strong><%= marker.updated_at ? new Date(marker.updated_at).toLocaleString() : "unknown" %></strong></div>
  </div>
  <% if (marker.error) { %><p class="hint status-danger"><%= marker.error %></p><% } %>
  <% } %>
  <div class="inline-actions">
    <form method="post" action="/admin/updates/recovery/clear-marker" data-update-action data-confirm-mode="modal" data-confirm-title="Clear recovery marker" data-confirm-text="Clear the stale recovery marker? Do this only after you have verified Lumi starts normally." data-confirm-label="Clear marker">
      <button class="button danger" type="submit">Clear stale marker</button>
    </form>
    <form method="post" action="/admin/updates/recovery/retry-normal-startup" data-update-action data-confirm-mode="modal" data-confirm-title="Retry normal startup" data-confirm-text="Restart Lumi and try a normal startup. Keep this page open while Lumi reconnects." data-confirm-label="Restart Lumi">
      <button class="button subtle" type="submit">Retry normal startup</button>
    </form>
  </div>
</section>
<% } %>
</div>

<section class="card" data-update-panel data-update-target="core" data-update-key="core">
  <details class="lumi-expandable-settings" <%= core?.blocked || core?.update_available || recovery.has_incomplete_marker ? "open" : "" %>>
    <summary>
      <span>
        <strong>Core</strong>
        <span class="hint" data-update-summary>Current <%= core?.current_version || "unknown" %> · Recommended <%= core?.safe_target_version || "none" %> · <%= core?.source_branch || "main" %></span>
      </span>
      <span class="badge <%= badgeClass(core) %>" data-update-badge><%= badgeText(core) %></span>
    </summary>
    <div class="lumi-expandable-body update-detail-grid">
      <% if (core) { %>
      <div class="update-meta-grid">
        <div><span>Current</span><strong data-update-field="current_version"><%= core.current_version %></strong></div>
        <div><span>Recommended version</span><strong data-update-field="safe_target_version"><%= core.safe_target_version || "None" %></strong></div>
        <div><span>Latest found</span><strong data-update-field="latest_available_version"><%= core.latest_available_version %></strong></div>
        <div><span>Update source</span><strong data-update-field="source_branch"><%= core.source_branch %></strong></div>
        <div><span>Size change</span><strong><%= core.size_delta_label %></strong></div>
        <div><span>Snapshot</span><strong><%= core.snapshot.available ? core.snapshot.latest_snapshot_id : "None" %></strong></div>
      </div>
      <p data-update-description><%= core.version_description %></p>
      <% if (core.warnings?.length) { %><div class="callout"><strong>Warnings</strong><ul><% core.warnings.forEach((item) => { %><li><%= item %></li><% }) %></ul></div><% } %>
      <% if (core.unversioned_update) { %><div class="callout danger"><strong>Manual confirmation required</strong><p>This core update is to or from an unversioned state. It remains available, but restore safety and version order cannot be fully verified from metadata.</p></div><% } %>
      <% if (core.dangers?.length) { %><div class="callout danger"><strong>Dangers</strong><ul><% core.dangers.forEach((item) => { %><li><%= item %></li><% }) %></ul></div><% } %>
      <% if (core.requirements?.length) { %><div class="callout"><strong>Requirements</strong><ul><% core.requirements.forEach((item) => { %><li><%= item %></li><% }) %></ul></div><% } %>
      <% if (core.migration_notes) { %><div class="callout"><strong>Migration notes</strong><p><%= core.migration_notes %></p></div><% } %>
      <div>
        <h3>Changelog to target</h3>
        <% if (!changelogItems(core).length) { %>
        <p class="hint">No changelog entries were found for this range.</p>
        <% } else { %>
        <ul class="update-changelog">
          <% changelogItems(core).forEach((entry) => { %>
          <li><strong><%= entry.version %></strong><span><%= Array.isArray(entry.changes) ? entry.changes.join(" ") : (entry.description || entry.title || "") %></span></li>
          <% }) %>
        </ul>
        <% } %>
      </div>
      <div class="inline-actions update-action-row">
        <form method="post" action="/admin/updates/core/check" data-update-action data-update-check-form>
          <input type="hidden" name="source" value="<%= selectedSource %>" />
          <button class="button subtle" type="submit" data-update-check-button>Check for updates</button>
        </form>
        <form method="post" action="/admin/updates/core/apply" data-update-action data-confirm-mode="modal" data-confirm-title="<%= core.unversioned_update ? "Apply unversioned core update" : "Apply core update" %>" data-confirm-text="<%= applyConfirmText(core, "Core update") %>" data-confirm-label="<%= applyLabel(core) %>">
          <input type="hidden" name="source" value="<%= selectedSource %>" />
          <button class="button" type="submit" data-update-apply-button <%= core.blocked || !core.update_available ? "disabled" : "" %>><%= core.unversioned_update ? "Review and update" : "Update core" %></button>
        </form>
        <% if (core.snapshot.available) { %>
        <form method="post" action="/admin/updates/core/revert" data-update-action data-confirm-mode="modal" data-confirm-title="Restore previous core backup" data-confirm-text="Restore only the previous core backup. Major-version restore is blocked unless metadata marks it safe." data-confirm-label="Restore core">
          <input type="hidden" name="source" value="<%= selectedSource %>" />
          <input type="hidden" name="snapshot_id" value="<%= core.snapshot.latest_snapshot_id %>" />
          <button class="button danger" type="submit">Restore previous version</button>
        </form>
        <% } %>
      </div>
      <p class="hint" data-update-inline-result aria-live="polite"></p>
      <% if (core.available_versions?.length) { %>
      <details class="lumi-expandable-settings update-version-picker">
        <summary>
          <span><strong>Install a specific core version</strong><span class="hint">Advanced version selection</span></span>
        </summary>
        <div class="lumi-expandable-body">
          <form method="post" action="/admin/updates/core/apply" class="input-action-row" data-update-action data-confirm-mode="modal" data-confirm-title="Install selected core version" data-confirm-text="Create a backup, preserve local data, install the exact tagged core release, verify its version, and restart Lumi. Older code may not understand database changes made by a newer release." data-confirm-label="Install selected version">
            <input type="hidden" name="source" value="<%= selectedSource %>" />
            <label class="field">
              <span>Core version</span>
              <select name="version" required>
                <% core.available_versions.forEach((release) => { %>
                <option value="<%= release.version %>"><%= release.version %></option>
                <% }) %>
              </select>
            </label>
            <button class="button subtle" type="submit">Install selected version</button>
          </form>
          <p class="hint">The selected core version is read from its immutable repository tag and verified before files are replaced. Local data remains in place.</p>
        </div>
      </details>
      <% } %>
      <% } %>
    </div>
  </details>
</section>

<section class="card" data-update-panel>
  <details class="lumi-expandable-settings" <%= summary.updatable_plugins || summary.blocked_plugins ? "open" : "" %>>
    <summary>
      <span>
        <strong>Plugins</strong>
        <span class="hint"><%= summary.installed_plugins %> installed · <%= summary.total_plugins %> known · <%= summary.updatable_plugins %> updatable</span>
      </span>
      <span class="badge <%= summary.blocked_plugins ? "danger" : summary.updatable_plugins ? "warning" : "success" %>"><%= summary.blocked_plugins ? `${summary.blocked_plugins} blocked` : `${summary.updatable_plugins} updates` %></span>
    </summary>
    <div class="lumi-expandable-body plugin-update-list">
      <% if (!plugins.length) { %>
      <div class="empty-state">No installed plugins found.</div>
      <% } %>
      <% plugins.forEach((plugin) => { %>
      <details class="lumi-expandable-settings plugin-update-row" data-update-key="plugin:<%= plugin.id %>" <%= plugin.blocked || plugin.update_available ? "open" : "" %>>
        <summary>
          <span>
            <strong><%= plugin.name %></strong>
            <span class="hint" data-update-summary><%= plugin.installed === false ? "Not installed" : plugin.current_version %> -> <%= plugin.safe_target_version || "none" %> · <%= plugin.source_branch %></span>
          </span>
          <span class="badge <%= badgeClass(plugin) %>" data-update-badge><%= badgeText(plugin) %></span>
        </summary>
        <div class="lumi-expandable-body update-detail-grid">
          <div class="update-meta-grid">
            <div><span>Current</span><strong data-update-field="current_version"><%= plugin.current_version %></strong></div>
            <div><span>Recommended version</span><strong data-update-field="safe_target_version"><%= plugin.safe_target_version || "None" %></strong></div>
            <div><span>Latest found</span><strong data-update-field="latest_available_version"><%= plugin.latest_available_version %></strong></div>
            <div><span>Snapshot</span><strong><%= plugin.snapshot.available ? plugin.snapshot.latest_snapshot_id : "None" %></strong></div>
          </div>
          <p data-update-description><%= plugin.version_description %></p>
          <% const tools = Array.isArray(plugin.tools) ? plugin.tools : []; %>
          <% if (plugin.id === "lumi_ai" && tools.length) { %>
          <% const toolSummary = plugin.tools_summary || {}; %>
          <details class="lumi-expandable-settings plugin-tool-list" <%= tools.some((tool) => tool.blocked || tool.update_available || tool.installed === false) ? "open" : "" %>>
            <summary>
              <span>
                <strong>Lumi AI tools</strong>
                <span class="hint"><%= toolSummary.installed_tools || 0 %> installed · <%= toolSummary.total_tools || tools.length %> known · <%= toolSummary.updatable_tools || 0 %> updatable · <%= toolSummary.available_tools || 0 %> available</span>
              </span>
              <span class="badge <%= toolSummary.blocked_tools ? "danger" : (toolSummary.updatable_tools || toolSummary.available_tools) ? "warning" : "success" %>"><%= toolSummary.blocked_tools ? `${toolSummary.blocked_tools} blocked` : `${(toolSummary.updatable_tools || 0) + (toolSummary.available_tools || 0)} actions` %></span>
            </summary>
            <div class="lumi-expandable-body plugin-update-list">
              <% tools.forEach((tool) => { %>
              <details class="lumi-expandable-settings plugin-update-row" <%= tool.blocked || tool.update_available || tool.installed === false ? "open" : "" %>>
                <summary>
                  <span>
                    <strong><%= tool.name %></strong>
                    <span class="hint"><%= tool.installed === false ? "Not installed" : tool.current_version %> -> <%= tool.safe_target_version || "none" %> · <%= tool.repository_path || `plugins/${tool.id}` %></span>
                  </span>
                  <span class="badge <%= toolBadgeClass(tool) %>"><%= toolBadgeText(tool) %></span>
                </summary>
                <div class="lumi-expandable-body update-detail-grid">
                  <div class="update-meta-grid">
                    <div><span>Current</span><strong><%= tool.installed === false ? "Not installed" : tool.current_version %></strong></div>
                    <div><span>Target</span><strong><%= tool.safe_target_version || "None" %></strong></div>
                    <div><span>Minimum Lumi AI</span><strong><%= tool.minimum_lumi_ai_version || "Not specified" %></strong></div>
                    <div><span>Source branch</span><strong><%= tool.source_branch %></strong></div>
                  </div>
                  <% if (tool.description) { %><p><%= tool.description %></p><% } %>
                  <% if (tool.warnings?.length) { %><div class="callout"><strong>Warnings</strong><ul><% tool.warnings.forEach((item) => { %><li><%= item %></li><% }) %></ul></div><% } %>
                  <% if (tool.dangers?.length) { %><div class="callout danger"><strong>Dangers</strong><ul><% tool.dangers.forEach((item) => { %><li><%= item %></li><% }) %></ul></div><% } %>
                  <% if (tool.capabilities?.length) { %>
                  <div>
                    <h3>Capabilities</h3>
                    <ul class="update-changelog">
                      <% tool.capabilities.forEach((item) => { %><li><span><%= item %></span></li><% }) %>
                    </ul>
                  </div>
                  <% } %>
                  <p class="hint">Lumi AI tools are installed and managed by the Lumi AI tool manager. They are not normal plugin registry entries.</p>
                </div>
              </details>
              <% }) %>
            </div>
          </details>
          <% } %>
          <% if (plugin.warnings?.length) { %><div class="callout"><strong>Warnings</strong><ul><% plugin.warnings.forEach((item) => { %><li><%= item %></li><% }) %></ul></div><% } %>
          <% if (plugin.unversioned_update) { %><div class="callout danger"><strong>Manual confirmation required</strong><p>This plugin update is to or from an unversioned state. It remains available, but restore safety and version order cannot be fully verified from metadata.</p></div><% } %>
          <% if (plugin.dangers?.length) { %><div class="callout danger"><strong>Dangers</strong><ul><% plugin.dangers.forEach((item) => { %><li><%= item %></li><% }) %></ul></div><% } %>
          <% if (plugin.migration_notes) { %><div class="callout"><strong>Migration notes</strong><p><%= plugin.migration_notes %></p></div><% } %>
          <h3>Changelog to target</h3>
          <% if (!changelogItems(plugin).length) { %>
          <p class="hint">No changelog entries were found for this range.</p>
          <% } else { %>
          <ul class="update-changelog">
            <% changelogItems(plugin).forEach((entry) => { %>
            <li><strong><%= entry.version %></strong><span><%= Array.isArray(entry.changes) ? entry.changes.join(" ") : (entry.description || entry.title || "") %></span></li>
            <% }) %>
          </ul>
          <% } %>
          <div class="inline-actions update-action-row">
            <form method="post" action="/admin/updates/plugins/<%= plugin.id %>/check" data-update-action data-update-check-form>
              <input type="hidden" name="source" value="<%= selectedSource %>" />
              <button class="button subtle" type="submit" data-update-check-button>Check for updates</button>
            </form>
            <form method="post" action="/admin/updates/plugins/<%= plugin.id %>/apply" data-update-action data-confirm-mode="modal" data-confirm-title="<%= plugin.unversioned_update ? `Apply unversioned ${plugin.name} update` : "Apply plugin update" %>" data-confirm-text="<%= applyConfirmText(plugin, `${plugin.name} update`) %>" data-confirm-label="<%= applyLabel(plugin) %>">
              <input type="hidden" name="source" value="<%= selectedSource %>" />
              <button class="button" type="submit" data-update-apply-button <%= plugin.blocked || !plugin.update_available ? "disabled" : "" %>><%= plugin.installed === false ? "Install from repo" : "Update plugin" %></button>
            </form>
            <% if (plugin.snapshot.available) { %>
            <form method="post" action="/admin/updates/plugins/<%= plugin.id %>/revert" data-update-action data-confirm-mode="modal" data-confirm-title="Restore previous plugin backup" data-confirm-text="Restore only the previous plugin backup. Major-version restore is blocked unless metadata marks it safe." data-confirm-label="Restore plugin">
              <input type="hidden" name="source" value="<%= selectedSource %>" />
              <input type="hidden" name="snapshot_id" value="<%= plugin.snapshot.latest_snapshot_id %>" />
              <button class="button danger" type="submit">Restore previous version</button>
            </form>
            <% } %>
            <% if (plugin.installed !== false) { %>
            <form method="post" action="/admin/updates/plugins/<%= plugin.id %>/disable" data-update-action data-confirm-mode="modal" data-confirm-title="Disable plugin" data-confirm-text="Disable this plugin for recovery? Lumi may need a restart for already-loaded plugin code to unload." data-confirm-label="Disable plugin">
              <button class="button danger" type="submit">Disable temporarily</button>
            </form>
            <% } %>
          </div>
          <p class="hint" data-update-inline-result aria-live="polite"></p>
          <% if (plugin.available_versions?.length) { %>
          <details class="lumi-expandable-settings update-version-picker">
            <summary>
              <span><strong>Install a specific <%= plugin.name %> version</strong><span class="hint">Advanced version selection</span></span>
            </summary>
            <div class="lumi-expandable-body">
              <form method="post" action="/admin/updates/plugins/<%= plugin.id %>/apply" class="input-action-row" data-update-action data-confirm-mode="modal" data-confirm-title="Install selected <%= plugin.name %> version" data-confirm-text="Back up this plugin, preserve its data directory, install the exact tagged release, verify the plugin version, and restart Lumi. Older plugin code may not understand newer data changes." data-confirm-label="Install selected version">
                <input type="hidden" name="source" value="<%= selectedSource %>" />
                <label class="field">
                  <span><%= plugin.name %> version</span>
                  <select name="version" required>
                    <% plugin.available_versions.forEach((release) => { %>
                    <option value="<%= release.version %>"><%= release.version %></option>
                    <% }) %>
                  </select>
                </label>
                <button class="button subtle" type="submit">Install selected version</button>
              </form>
              <p class="hint">Only versions published for <%= plugin.name %> are listed. The plugin’s <code>data</code> folder is retained, and Lumi restarts to load the selected code.</p>
            </div>
          </details>
          <% } %>
        </div>
      </details>
      <% }) %>
    </div>
  </details>
</section>

<section class="card">
  <details class="lumi-expandable-settings">
    <summary>
      <span>
        <strong>Manual ZIP updates</strong>
        <span class="hint">Advanced fallback for recovery, offline installs, or when repository updates fail.</span>
      </span>
      <span class="badge warning">Advanced</span>
    </summary>
    <div class="lumi-expandable-body">
      <p class="hint">Repository updates are the recommended path. ZIP uploads still create backups and automatically restore them if file replacement fails, but they can bypass repository metadata and compatibility checks unless the ZIP includes valid manifest data.</p>
      <div class="grid">
        <div class="card">
          <h3>Core ZIP</h3>
          <p class="hint">Use a full core ZIP or a patch ZIP containing files relative to the Lumi install root.</p>
          <form method="post" action="/admin/updates/core/zip" enctype="multipart/form-data" class="form-grid" data-update-action data-confirm-mode="modal" data-confirm-title="Apply core ZIP update" data-confirm-text="Apply this manual core ZIP after creating a recovery snapshot? Keep this page open while Lumi restarts and reconnects." data-confirm-label="Apply core ZIP">
            <div class="field full input-action-row">
              <input type="file" name="update_zip" accept=".zip" required />
              <button type="submit" class="button">Upload core ZIP</button>
            </div>
            <label class="switch"><input type="checkbox" class="switch-input" name="patch_mode" value="1" /><span class="switch-track"></span><span class="switch-text">Patch mode</span></label>
            <label class="switch"><input type="checkbox" class="switch-input" name="rollback_safe" value="1" /><span class="switch-track"></span><span class="switch-text">ZIP notes say rollback is safe</span></label>
          </form>
        </div>
        <div class="card">
          <h3>Plugin ZIP</h3>
          <p class="hint">Use when plugin repository metadata is unavailable. Plugin ZIPs must include a valid <code>plugin.json</code>.</p>
          <form method="post" action="/admin/updates/plugin" enctype="multipart/form-data" class="form-grid" data-update-action data-confirm-mode="modal" data-confirm-title="Apply plugin ZIP update" data-confirm-text="Apply this manual plugin ZIP after creating a recovery snapshot? Keep this page open while Lumi restarts and reconnects." data-confirm-label="Apply plugin ZIP">
            <div class="field full input-action-row">
              <input type="file" name="plugin_zip" accept=".zip" required />
              <button type="submit" class="button">Upload plugin ZIP</button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </details>
</section>

<section class="card">
  <h2>Live Progress</h2>
  <div class="update-progress-log" data-update-progress-log role="log" aria-label="Update and recovery progress" aria-live="polite" aria-relevant="additions" tabindex="0">
    <div class="hint">Update and recovery progress appears here while actions run.</div>
  </div>
</section>

<section class="card">
  <h2>Snapshots</h2>
  <p class="hint">Snapshots contain compressed rollback code and a compressed database backup. Preserved local data—such as AI models, runtimes, uploads, logs, plugin data, and community knowledge—is kept in place during updates and is not copied into new snapshots.</p>
  <fieldset class="lumi-fieldset">
    <legend>Automatic snapshot cleanup</legend>
    <form method="post" action="/admin/updates/snapshots/settings" class="form-grid" data-update-action data-update-settings-form>
      <label>Maximum age in days
        <input type="number" name="max_age_days" min="1" max="3650" value="<%= retention.max_age_days %>" required />
        <span class="hint">Snapshots older than this are removed, even if the count limit has not been reached.</span>
      </label>
      <label>Latest backups per target
        <input type="number" name="max_per_target" min="1" max="50" value="<%= retention.max_per_target %>" required />
        <span class="hint">Applied separately to core and each plugin, so one frequently updated target cannot crowd out the others.</span>
      </label>
      <div class="inline-actions full">
        <button class="button" type="submit">Save cleanup policy</button>
      </div>
    </form>
  </fieldset>
  <% if (!snapshots.length) { %>
  <div class="empty-state">No snapshots yet.</div>
  <% } else { %>
  <div class="table-wrap">
    <table class="table" data-update-snapshot-table>
      <thead>
        <tr>
          <th>Target</th>
          <th>Version</th>
          <th>Method</th>
          <th>Rollback</th>
          <th>Stored size</th>
          <th>Created</th>
        </tr>
      </thead>
      <tbody>
        <% snapshots.forEach((snap) => { %>
        <tr>
          <td data-label="Target"><%= snap.type === "plugin" ? `Plugin: ${snap.pluginId}` : "Core" %></td>
          <td data-label="Version"><%= snap.from_version || "?" %> -> <%= snap.to_version || "?" %></td>
          <td data-label="Method"><%= snap.update_method || "snapshot" %></td>
          <td data-label="Rollback"><%= snap.major_crossing && snap.rollback_safe === false ? "Blocked after major migration" : "Previous-version restore allowed" %></td>
          <td data-label="Stored size"><%= formatBytes(snap.storage_bytes) %><%= snap.compressed ? " · compressed" : "" %></td>
          <td data-label="Created"><%= new Date(snap.createdAt).toLocaleString() %></td>
        </tr>
        <% }) %>
      </tbody>
    </table>
  </div>
  <% } %>
</section>
</div>
<%- include("partials/layout-bottom") %>
