<%- include("partials/layout-top", { title }) %>
<%
  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 update" : "Use recommended version";
  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}`;
  };
%>

<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">
    <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"></div>

<% 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-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">
      <button class="button subtle" type="submit">Retry normal startup</button>
    </form>
  </div>
</section>
<% } %>

<section class="card" data-update-panel data-update-target="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>
          <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>
      <% } %>
    </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" <%= 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>
              <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-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>
        </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">
            <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">
            <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>
    <div class="hint">Update and recovery progress appears here while actions run.</div>
  </div>
</section>

<section class="card">
  <h2>Snapshots</h2>
  <% if (!snapshots.length) { %>
  <div class="empty-state">No snapshots yet.</div>
  <% } else { %>
  <div class="table-wrap">
    <table class="table">
      <thead>
        <tr>
          <th>Target</th>
          <th>Version</th>
          <th>Method</th>
          <th>Rollback</th>
          <th>Created</th>
        </tr>
      </thead>
      <tbody>
        <% snapshots.forEach((snap) => { %>
        <tr>
          <td><%= snap.type === "plugin" ? `Plugin: ${snap.pluginId}` : "Core" %></td>
          <td><%= snap.from_version || "?" %> -> <%= snap.to_version || "?" %></td>
          <td><%= snap.update_method || "snapshot" %></td>
          <td><%= snap.major_crossing && snap.rollback_safe === false ? "Blocked after major migration" : "Previous-version restore allowed" %></td>
          <td><%= new Date(snap.createdAt).toLocaleString() %></td>
        </tr>
        <% }) %>
      </tbody>
    </table>
  </div>
  <% } %>
</section>
<script>
(() => {
  const root = document.querySelector("[data-update-notices]");
  const badgeClass = (item) => item?.blocked ? "danger" : item?.update_available ? "warning" : "success";
  const badgeText = (item) => item?.blocked ? "Blocked" : item?.update_available ? "Update available" : "Current";

  const showNotice = (message, tone = "info") => {
    if (!root) return;
    const item = document.createElement("div");
    item.className = `update-notice ${tone}`;
    item.setAttribute("role", tone === "danger" ? "alert" : "status");
    const text = document.createElement("span");
    text.textContent = message || "Update status changed.";
    const close = document.createElement("button");
    close.type = "button";
    close.className = "icon-button";
    close.setAttribute("aria-label", "Dismiss notification");
    close.textContent = "×";
    close.addEventListener("click", () => item.remove());
    item.append(text, close);
    root.append(item);
    if (!["danger", "warning"].includes(tone)) {
      window.setTimeout(() => item.remove(), 6500);
    }
  };

  const setButtonLoading = (button, loading) => {
    if (!button) return;
    if (loading) {
      button.dataset.originalText = button.textContent;
      button.textContent = "Checking...";
      button.disabled = true;
      button.setAttribute("aria-busy", "true");
    } else {
      button.textContent = button.dataset.originalText || "Check for updates";
      button.disabled = false;
      button.setAttribute("aria-busy", "false");
    }
  };

  const setText = (row, selector, value) => {
    const target = row.querySelector(selector);
    if (target) target.textContent = value || "None";
  };

  const updateRow = (row, item) => {
    if (!row || !item) return;
    const summary = row.querySelector("[data-update-summary]");
    if (summary) {
      const current = item.installed === false ? "Not installed" : item.current_version;
      summary.textContent = `${current || "unknown"} -> ${item.safe_target_version || "none"} · ${item.source_branch || "main"}`;
    }
    const badge = row.querySelector("[data-update-badge]");
    if (badge) {
      badge.className = `badge ${badgeClass(item)}`;
      badge.textContent = badgeText(item);
    }
    setText(row, "[data-update-field='current_version']", item.current_version);
    setText(row, "[data-update-field='safe_target_version']", item.safe_target_version);
    setText(row, "[data-update-field='latest_available_version']", item.latest_available_version);
    setText(row, "[data-update-field='source_branch']", item.source_branch);
    setText(row, "[data-update-description]", item.version_description);
    const apply = row.querySelector("[data-update-apply-button]");
    if (apply) apply.disabled = Boolean(item.blocked || !item.update_available);
  };

  document.querySelectorAll("form[data-update-action]").forEach((form) => {
    if (!form.action.endsWith("/check")) return;
    form.addEventListener("submit", async (event) => {
      event.preventDefault();
      const button = event.submitter || form.querySelector("[data-update-check-button]");
      const row = form.closest(".plugin-update-row, [data-update-target='core']");
      setButtonLoading(button, true);
      try {
        const response = await fetch(form.action, {
          method: "POST",
          body: new FormData(form),
          headers: { Accept: "application/json" },
          credentials: "same-origin"
        });
        const payload = await response.json().catch(() => ({}));
        if (!response.ok || payload.ok === false) {
          throw new Error(payload.error || "The update check failed.");
        }
        const item = payload.plugin || payload.status?.core;
        updateRow(row, item);
        const tone = item?.blocked ? "danger" : item?.update_available ? "warning" : "success";
        showNotice(payload.message || (item?.update_available ? "Updates are available." : "No updates found."), tone);
      } catch (error) {
        showNotice(error.message || "The update check failed. Try again or use manual ZIP recovery if repository checks keep failing.", "danger");
      } finally {
        setButtonLoading(button, false);
      }
    });
  });
})();
</script>
<%- include("partials/layout-bottom") %>
