// ========== UPDATE MANAGEMENT ==========
(function() {
  // Inject modal HTML
  injectModal('updates-modal', `<div id="updates-modal" class="weather-modal">
    <div class="weather-modal-content" style="min-width: 750px; max-width: 950px;">
      <h3>⬆️ Update Management</h3>
      <p class="modal-subtitle">
        Check for container image updates, apply them, and manage rollbacks.
      </p>

      <div class="panel-tabs">
        <button class="panel-tab active" data-panel="updates-available">Available</button>
        <button class="panel-tab" data-panel="updates-history">History</button>
        <button class="panel-tab" data-panel="updates-auto">Auto-Update</button>
        <button class="panel-tab" data-panel="updates-dashcaddy" id="updates-dashcaddy-tab">DashCaddy</button>
      </div>

      <!-- Tab: Available Updates -->
      <div id="updates-available" class="panel-section active">
        <div style="margin-bottom: 12px; display: flex; gap: 8px; align-items: center;">
          <button id="updates-check-btn" class="btn-accent-solid">🔍 Check for Updates</button>
          <button id="updates-update-all-btn" style="display: none; padding: 6px 14px; font-size: 0.82rem; background: #f97316; color: #fff; border: 1px solid #f97316; border-radius: 6px; cursor: pointer;">⬆️ Update All</button>
          <span id="updates-count-badge" style="display: none; padding: 4px 10px; border-radius: 12px; font-size: 0.78rem; font-weight: 600; background: var(--accent); color: var(--bg);"></span>
        </div>
        <div id="updates-available-container" style="max-height: 450px; overflow-y: auto;">
          <div class="panel-empty"><span class="empty-icon">📦</span> Click "Check for Updates" to scan containers.</div>
        </div>
      </div>

      <!-- Tab: History -->
      <div id="updates-history" class="panel-section">
        <div id="updates-history-container" class="scroll-container">
          <div class="panel-empty"><span class="brand-spinner"></span> Loading update history...</div>
        </div>
      </div>

      <!-- Tab: Auto-Update -->
      <div id="updates-auto" class="panel-section">
        <div id="updates-auto-container" class="scroll-container">
          <div class="panel-empty"><span class="empty-icon">🤖</span> Loading auto-update configuration...</div>
        </div>
      </div>

      <!-- Tab: DashCaddy Self-Update -->
      <div id="updates-dashcaddy" class="panel-section">
        <div id="dashcaddy-version-info" style="display: flex; align-items: center; gap: 16px; margin-bottom: 16px; padding: 12px; border-radius: 8px; background: var(--bg);">
          <div style="flex: 1;">
            <div style="font-weight: 600; font-size: 1rem;">DashCaddy</div>
            <div id="dashcaddy-current-version" style="color: var(--muted); font-size: 0.85rem;">Loading...</div>
          </div>
          <div id="dashcaddy-update-badge" style="display: none; padding: 4px 12px; border-radius: 12px; font-size: 0.78rem; font-weight: 600; background: var(--accent); color: var(--bg);">Update available</div>
        </div>
        <div id="dashcaddy-update-details" style="display: none; margin-bottom: 16px; padding: 12px; border-radius: 8px; border: 1px solid var(--border);">
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
            <span style="font-weight: 600;">New version: <span id="dashcaddy-new-version"></span></span>
            <button id="dashcaddy-apply-btn" class="btn-accent-solid" style="padding: 6px 16px; font-size: 0.85rem;">Update Now</button>
          </div>
          <div id="dashcaddy-changelog" style="font-size: 0.8rem; color: var(--muted); max-height: 120px; overflow-y: auto; white-space: pre-wrap; font-family: var(--font-mono); line-height: 1.5;"></div>
        </div>
        <div id="dashcaddy-status-bar" style="display: none; margin-bottom: 16px; padding: 10px 12px; border-radius: 8px; font-size: 0.85rem;"></div>
        <div style="margin-bottom: 12px;">
          <button id="dashcaddy-check-btn" style="padding: 6px 14px; font-size: 0.82rem;">Check for Updates</button>
          <button id="dashcaddy-rollback-btn" style="padding: 6px 14px; font-size: 0.82rem; margin-left: 6px;">Rollback</button>
        </div>
        <div id="dashcaddy-history-container" style="max-height: 250px; overflow-y: auto;">
          <div class="panel-empty"><span class="empty-icon">📦</span>No self-update history.</div>
        </div>
      </div>

      <div class="panel-bottom-bar">
        <span id="updates-last-check" class="text-auto-right"></span>
      </div>

      <div class="weather-modal-buttons modal-footer-bar">
        <button id="updates-cancel">Close</button>
      </div>
    </div>
  </div>`);

  const modal = document.getElementById('updates-modal');
  const openBtn = document.getElementById('updates-btn');
  const cancelBtn = document.getElementById('updates-cancel');
  const checkBtn = document.getElementById('updates-check-btn');
  const availableContainer = document.getElementById('updates-available-container');
  const historyContainer = document.getElementById('updates-history-container');
  const autoContainer = document.getElementById('updates-auto-container');
  const lastCheckSpan = document.getElementById('updates-last-check');

  async function loadAvailable() {
    try {
      const res = await fetch('/api/v1/updates/available');
      const data = await res.json();
      if (!data.success) throw new Error(data.error);

      const updates = data.updates || [];
      if (updates.length === 0) {
        availableContainer.innerHTML = '<div class="panel-empty"><span class="empty-icon">✅</span>All containers are up to date.</div>';
        lastCheckSpan.textContent = '';
        document.getElementById('updates-update-all-btn').style.display = 'none';
        document.getElementById('updates-count-badge').style.display = 'none';
        window._pendingUpdates = [];
        return;
      }

      let html = '<table style="width: 100%; border-collapse: collapse; font-size: 0.85rem;">';
      html += '<tr style="border-bottom: 1px solid var(--border); color: var(--muted);"><th style="padding: 8px; text-align: left;">Container</th><th style="padding: 8px; text-align: left;">Image</th><th style="padding: 8px; text-align: left;">Current</th><th style="padding: 8px; text-align: left;">Latest</th><th style="padding: 8px; text-align: right;">Actions</th></tr>';
      for (const u of updates) {
        // Match app by containerId first, then name
        const appId = (() => {
          const apps = window.APPS || [];
          for (const a of apps) {
            if (a.containerId === u.containerId || a.name === u.containerName || a.id === u.containerName) return a.id;
          }
          return u.containerName;
        })();
        html += `<tr data-app-id="${escapeHtml(appId)}" style="border-bottom: 1px solid var(--border);">`;
        html += `<td style="padding: 8px; font-weight: 500;">${escapeHtml(u.containerName)}</td>`;
        html += `<td style="padding: 8px; color: var(--muted);">${escapeHtml(u.imageName)}</td>`;
        html += `<td style="padding: 8px;"><code style="font-size: 0.78rem; background: var(--bg); padding: 2px 6px; border-radius: 4px;">${escapeHtml(u.currentDigest)}</code></td>`;
        html += `<td style="padding: 8px;"><code style="font-size: 0.78rem; background: var(--ok-bg); color: var(--ok-fg); padding: 2px 6px; border-radius: 4px;">${escapeHtml(u.latestDigest)}</code></td>`;
        html += `<td style="padding: 8px; text-align: right;">`;
        html += `<button class="update-now-btn" data-id="${escapeHtml(u.containerId)}" data-name="${escapeHtml(u.containerName)}" style="padding: 4px 10px; font-size: 0.78rem; background: var(--accent); color: var(--bg); border-color: var(--accent); margin-right: 4px;">Update</button>`;
        html += `<button class="rollback-btn" data-id="${escapeHtml(u.containerId)}" data-name="${escapeHtml(u.containerName)}" style="padding: 4px 10px; font-size: 0.78rem;">Rollback</button>`;
        html += '</td></tr>';
      }
      html += '</table>';
      availableContainer.innerHTML = html;
      lastCheckSpan.textContent = updates.length + ' update(s) available';

      // Show count badge and Update All button
      const countBadge = document.getElementById('updates-count-badge');
      const updateAllBtn = document.getElementById('updates-update-all-btn');
      if (countBadge) {
        countBadge.textContent = updates.length + ' pending';
        countBadge.style.display = '';
      }
      if (updateAllBtn && updates.length > 0) {
        updateAllBtn.style.display = '';
      }

      // Store updates for Update All button
      window._pendingUpdates = updates;

      // Wire update buttons
      availableContainer.querySelectorAll('.update-now-btn').forEach(btn => {
        btn.addEventListener('click', async () => {
          const id = btn.dataset.id;
          const name = btn.dataset.name;
          if (!confirm(`Update "${name}" to the latest version? The container will restart.`)) return;
          btn.textContent = 'Updating...';
          btn.disabled = true;
          try {
            const r = await secureFetch(`/api/v1/updates/update/${encodeURIComponent(id)}`, {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ autoRollback: true })
            });
            const d = await r.json();
            if (d.success) {
              btn.textContent = 'Done!';
              btn.style.background = 'var(--ok-fg)';
              setTimeout(() => loadAvailable(), 2000);
            } else {
              throw new Error(d.error || 'Update failed');
            }
          } catch (e) {
            btn.textContent = 'Failed';
            btn.style.color = 'var(--bad-fg)';
            showNotification('Update error: ' + e.message, 'error');
            setTimeout(() => { btn.textContent = 'Update'; btn.disabled = false; btn.style.color = ''; btn.style.background = ''; }, 3000);
          }
        });
      });

      // Wire rollback buttons
      availableContainer.querySelectorAll('.rollback-btn').forEach(btn => {
        btn.addEventListener('click', async () => {
          const id = btn.dataset.id;
          const name = btn.dataset.name;
          if (!confirm(`Rollback "${name}" to its previous version?`)) return;
          btn.textContent = 'Rolling back...';
          btn.disabled = true;
          try {
            const r = await secureFetch(`/api/v1/updates/rollback/${encodeURIComponent(id)}`, { method: 'POST' });
            const d = await r.json();
            if (d.success) {
              btn.textContent = 'Rolled back!';
              setTimeout(() => loadAvailable(), 2000);
            } else {
              throw new Error(d.error || 'Rollback failed');
            }
          } catch (e) {
            btn.textContent = 'Failed';
            showNotification('Rollback error: ' + e.message, 'error');
            setTimeout(() => { btn.textContent = 'Rollback'; btn.disabled = false; }, 3000);
          }
        });
      });
    } catch (e) {
      availableContainer.innerHTML = `<div class="panel-empty" style="color: var(--bad-fg);">Failed: ${escapeHtml(e.message)}</div>`;
    }
  }

  // Update All — sequentially, skip failures
  async function updateAllContainers() {
    const updates = window._pendingUpdates || [];
    if (!updates.length) return;
    const btn = document.getElementById('updates-update-all-btn');
    if (!confirm(`Update all ${updates.length} containers? Each will restart.`)) return;
    btn.textContent = '⏳ Updating...';
    btn.disabled = true;
    let success = 0, failed = 0;
    for (const u of updates) {
      try {
        const r = await secureFetch(`/api/v1/updates/update/${encodeURIComponent(u.containerId)}`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ autoRollback: true })
        });
        const d = await r.json();
        if (d.success) success++;
        else failed++;
      } catch (_) { failed++; }
    }
    btn.textContent = `✅ Done`;
    showNotification(`Update all: ${success} succeeded, ${failed} failed.`, success > 0 && failed === 0 ? 'success' : 'error');
    setTimeout(() => {
      btn.textContent = '⬆️ Update All';
      btn.disabled = false;
      loadAvailable();
    }, 3000);
  }

  document.getElementById('updates-update-all-btn')?.addEventListener('click', updateAllContainers);

  async function checkForUpdates() {
    checkBtn.textContent = '🔍 Checking...';
    checkBtn.disabled = true;
    try {
      const res = await secureFetch('/api/v1/updates/check', { method: 'POST' });
      const data = await res.json();
      if (!data.success) throw new Error(data.error);
      checkBtn.textContent = '✅ Done!';
      await loadAvailable();
    } catch (e) {
      checkBtn.textContent = '❌ Failed';
      showNotification('Check error: ' + e.message, 'error');
    }
    setTimeout(() => { checkBtn.textContent = '🔍 Check for Updates'; checkBtn.disabled = false; }, 3000);
  }

  async function loadHistory() {
    try {
      historyContainer.innerHTML = '<div class="panel-empty"><span class="brand-spinner"></span> Loading...</div>';
      const res = await fetch('/api/v1/updates/history?limit=50');
      const data = await res.json();
      const history = data.success && data.history ? data.history : [];
      if (history.length === 0) {
        historyContainer.innerHTML = '<div class="panel-empty"><span class="empty-icon">📋</span>No update history yet.</div>';
        return;
      }
      let html = '<table style="width: 100%; border-collapse: collapse; font-size: 0.82rem;">';
      html += '<tr style="border-bottom: 1px solid var(--border); color: var(--muted);"><th style="padding: 6px; text-align: left;">When</th><th style="padding: 6px; text-align: left;">Container</th><th style="padding: 6px; text-align: left;">Image</th><th style="padding: 6px; text-align: left;">Duration</th><th style="padding: 6px; text-align: left;">Status</th></tr>';
      for (const h of history) {
        const ok = h.status === 'success';
        const dur = h.duration ? (h.duration < 1000 ? h.duration + 'ms' : Math.round(h.duration / 1000) + 's') : '-';
        html += `<tr style="border-bottom: 1px solid var(--border);">`;
        html += `<td style="padding: 6px; color: var(--muted);">${timeAgo(h.timestamp)}</td>`;
        html += `<td style="padding: 6px; font-weight: 500;">${escapeHtml(h.containerName)}</td>`;
        html += `<td style="padding: 6px; color: var(--muted);">${escapeHtml(h.imageName)}</td>`;
        html += `<td style="padding: 6px;">${dur}</td>`;
        html += `<td style="padding: 6px;"><span style="color: ${ok ? 'var(--ok-fg)' : 'var(--bad-fg)'};">${ok ? '✓ success' : '✗ failed'}</span></td>`;
        html += '</tr>';
        if (!ok && h.error) {
          html += `<tr><td colspan="5" style="padding: 4px 6px 8px; font-size: 0.78rem; color: var(--bad-fg);">${escapeHtml(h.error)}</td></tr>`;
        }
      }
      html += '</table>';
      historyContainer.innerHTML = html;
    } catch (e) {
      historyContainer.innerHTML = `<div class="panel-empty" style="color: var(--bad-fg);">Failed: ${escapeHtml(e.message)}</div>`;
    }
  }

  async function loadAutoConfig() {
    try {
      autoContainer.innerHTML = '<div class="panel-empty"><span class="brand-spinner"></span> Loading...</div>';

      // Fetch containers and saved auto-update config in parallel
      const [containersRes, configRes] = await Promise.all([
        fetch('/api/v1/stats/containers'),
        fetch('/api/v1/updates/auto-update')
      ]);
      const containersData = await containersRes.json();
      const configData = await configRes.json();

      const containers = containersData.success && containersData.stats ? containersData.stats : [];
      const savedConfig = configData.success && configData.config ? configData.config : {};

      if (containers.length === 0) {
        autoContainer.innerHTML = '<div class="panel-empty"><span class="empty-icon">🤖</span>No running containers found.</div>';
        return;
      }

      let html = '<div style="margin-bottom: 12px; font-size: 0.8rem; color: var(--muted);">Auto-updates run during maintenance window (default 2AM-4AM). Daily = every day, Weekly = Sundays, Monthly = 1st of month.</div>';
      html += '<table style="width: 100%; border-collapse: collapse; font-size: 0.85rem;">';
      html += '<tr style="border-bottom: 1px solid var(--border); color: var(--muted);"><th style="padding: 8px; text-align: left;">Container</th><th style="padding: 8px; text-align: left;">Schedule</th><th style="padding: 8px; text-align: left;">Window</th><th style="padding: 8px; text-align: left;">Rollback</th><th style="padding: 8px; text-align: left;">Last Run</th><th style="padding: 8px; text-align: right;">Actions</th></tr>';
      for (const c of containers) {
        const name = c.name || c.Names?.[0]?.replace(/^\//, '') || c.Id?.substring(0, 12);
        const cid = c.containerId || c.Id;
        const saved = savedConfig[cid] || {};
        const scheduleVal = saved.enabled ? (saved.schedule || 'weekly') : '';
        const rollbackVal = saved.autoRollback !== false;
        const windowVal = saved.maintenanceWindow || '';
        const lastRun = saved.lastAutoUpdate ? timeAgo(saved.lastAutoUpdate) : 'Never';

        html += `<tr style="border-bottom: 1px solid var(--border);" data-container-id="${escapeHtml(cid)}">`;
        html += `<td style="padding: 8px; font-weight: 500;">${escapeHtml(name)}</td>`;
        html += `<td style="padding: 8px;">
          <select class="auto-schedule" data-id="${escapeHtml(cid)}" style="padding: 4px 8px; border-radius: 4px; border: 1px solid var(--border); background: var(--bg); color: var(--fg); font-size: 0.82rem;">
            <option value=""${!scheduleVal ? ' selected' : ''}>Disabled</option>
            <option value="daily"${scheduleVal === 'daily' ? ' selected' : ''}>Daily</option>
            <option value="weekly"${scheduleVal === 'weekly' ? ' selected' : ''}>Weekly</option>
            <option value="monthly"${scheduleVal === 'monthly' ? ' selected' : ''}>Monthly</option>
          </select></td>`;
        html += `<td style="padding: 8px;"><input type="text" class="auto-window" data-id="${escapeHtml(cid)}" value="${escapeHtml(windowVal)}" placeholder="02:00-04:00" style="width: 90px; padding: 3px 6px; font-size: 0.78rem; border: 1px solid var(--border); border-radius: 4px; background: var(--bg); color: var(--fg);" /></td>`;
        html += `<td style="padding: 8px;"><input type="checkbox" class="auto-rollback" data-id="${escapeHtml(cid)}"${rollbackVal ? ' checked' : ''} /></td>`;
        html += `<td style="padding: 8px; font-size: 0.78rem; color: var(--muted);">${lastRun}</td>`;
        html += `<td style="padding: 8px; text-align: right;"><button class="save-auto-btn" data-id="${escapeHtml(cid)}" data-name="${escapeHtml(name)}" style="padding: 4px 10px; font-size: 0.78rem;">Save</button></td>`;
        html += '</tr>';
      }
      html += '</table>';
      autoContainer.innerHTML = html;

      // Wire save buttons
      autoContainer.querySelectorAll('.save-auto-btn').forEach(btn => {
        btn.addEventListener('click', async () => {
          const id = btn.dataset.id;
          const row = btn.closest('tr');
          const schedule = row.querySelector('.auto-schedule').value;
          const rollback = row.querySelector('.auto-rollback').checked;
          const window = row.querySelector('.auto-window').value.trim();
          btn.textContent = 'Saving...';
          btn.disabled = true;
          try {
            const r = await secureFetch(`/api/v1/updates/auto-update/${encodeURIComponent(id)}`, {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ enabled: !!schedule, schedule: schedule || 'weekly', autoRollback: rollback, maintenanceWindow: window || undefined })
            });
            const d = await r.json();
            if (d.success) {
              btn.textContent = '✓ Saved';
            } else {
              throw new Error(d.error);
            }
          } catch (e) {
            btn.textContent = '✗ Error';
            showNotification('Save error: ' + e.message, 'error');
          }
          setTimeout(() => { btn.textContent = 'Save'; btn.disabled = false; }, 2000);
        });
      });
    } catch (e) {
      autoContainer.innerHTML = `<div class="panel-empty" style="color: var(--bad-fg);">Failed: ${escapeHtml(e.message)}</div>`;
    }
  }

  // ===== DASHCADDY SELF-UPDATE =====

  const dcVersionInfo = document.getElementById('dashcaddy-current-version');
  const dcUpdateBadge = document.getElementById('dashcaddy-update-badge');
  const dcUpdateDetails = document.getElementById('dashcaddy-update-details');
  const dcNewVersion = document.getElementById('dashcaddy-new-version');
  const dcChangelog = document.getElementById('dashcaddy-changelog');
  const dcApplyBtn = document.getElementById('dashcaddy-apply-btn');
  const dcCheckBtn = document.getElementById('dashcaddy-check-btn');
  const dcRollbackBtn = document.getElementById('dashcaddy-rollback-btn');
  const dcStatusBar = document.getElementById('dashcaddy-status-bar');
  const dcHistoryContainer = document.getElementById('dashcaddy-history-container');

  let dcLastCheck = null;

  function dcShowStatus(msg, type) {
    if (!dcStatusBar) return;
    dcStatusBar.style.display = 'block';
    dcStatusBar.style.background = type === 'error' ? 'var(--bad-bg)' : type === 'success' ? 'var(--ok-bg)' : 'var(--bg)';
    dcStatusBar.style.color = type === 'error' ? 'var(--bad-fg)' : type === 'success' ? 'var(--ok-fg)' : 'var(--fg)';
    dcStatusBar.textContent = msg;
  }

  async function dcLoadVersion() {
    try {
      const res = await fetch('/api/v1/system/version');
      const data = await res.json();
      if (data.success) {
        const commit = data.commit && data.commit !== 'unknown' ? data.commit : null;
        dcVersionInfo.textContent = 'v' + data.version + (commit ? ' (' + commit.substring(0, 7) + ')' : '');
      }
    } catch (_) {
      dcVersionInfo.textContent = 'Unable to fetch version';
    }
  }

  async function dcCheckForUpdate(silent) {
    if (!silent) {
      dcCheckBtn.textContent = 'Checking...';
      dcCheckBtn.disabled = true;
    }
    try {
      const res = await fetch('/api/v1/system/update-check');
      const data = await res.json();
      dcLastCheck = data;

      if (data.success && data.available && data.remote) {
        dcUpdateBadge.style.display = '';
        dcUpdateDetails.style.display = '';
        dcNewVersion.textContent = 'v' + data.remote.version;
        dcChangelog.textContent = data.remote.changelog || 'No changelog available.';

        // Add notification dot to the Updates button
        const updatesBtn = document.getElementById('updates-btn');
        if (updatesBtn && !updatesBtn.querySelector('.update-dot')) {
          const dot = document.createElement('span');
          dot.className = 'update-dot';
          dot.style.cssText = 'position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--accent);';
          updatesBtn.style.position = 'relative';
          updatesBtn.appendChild(dot);
        }
        // Also add dot to the DashCaddy tab
        const dcTab = document.getElementById('updates-dashcaddy-tab');
        if (dcTab && !dcTab.querySelector('.update-dot')) {
          const dot = document.createElement('span');
          dot.className = 'update-dot';
          dot.style.cssText = 'display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--accent);margin-left:4px;vertical-align:middle;';
          dcTab.appendChild(dot);
        }
      } else {
        dcUpdateBadge.style.display = 'none';
        dcUpdateDetails.style.display = 'none';
        await dcLoadVersion();
        if (!silent) dcShowStatus('You are running the latest version.', 'success');
      }

      if (!silent) {
        dcCheckBtn.textContent = 'Check for Updates';
        dcCheckBtn.disabled = false;
      }
    } catch (e) {
      if (!silent) {
        dcShowStatus('Failed to check: ' + e.message, 'error');
        dcCheckBtn.textContent = 'Check for Updates';
        dcCheckBtn.disabled = false;
      }
    }
  }

  async function dcApplyUpdate() {
    if (!confirm('Apply DashCaddy update? The API container will restart.')) return false;
    dcApplyBtn.textContent = 'Updating...';
    dcApplyBtn.disabled = true;
    dcShowStatus('Downloading and applying update...', 'info');
    try {
      const res = await secureFetch('/api/v1/system/update-apply', { method: 'POST' });
      const data = await res.json();
      if (data.success) {
        dcShowStatus('Update initiated: v' + (data.fromVersion || '?') + ' → v' + (data.toVersion || '?') + '. The container will restart shortly.', 'success');
        dcApplyBtn.textContent = 'Applied!';
        // Remove notification dots
        document.querySelectorAll('.update-dot').forEach(d => d.remove());
        return true;
      } else {
        throw new Error(data.error || 'Update failed');
      }
    } catch (e) {
      dcShowStatus('Update failed: ' + e.message, 'error');
      dcApplyBtn.textContent = 'Update Now';
      dcApplyBtn.disabled = false;
      throw e;
    }
  }

  async function dcLoadHistory() {
    try {
      const res = await fetch('/api/v1/system/update-history');
      const data = await res.json();
      const history = data.success && data.history ? data.history : [];
      if (history.length === 0) {
        dcHistoryContainer.innerHTML = '<div class="panel-empty"><span class="empty-icon">📦</span>No self-update history.</div>';
        return;
      }
      let html = '<table style="width: 100%; border-collapse: collapse; font-size: 0.82rem;">';
      html += '<tr style="border-bottom: 1px solid var(--border); color: var(--muted);"><th style="padding: 6px; text-align: left;">When</th><th style="padding: 6px; text-align: left;">Version</th><th style="padding: 6px; text-align: left;">From</th><th style="padding: 6px; text-align: left;">Status</th></tr>';
      for (const h of history) {
        const st = h.status === 'success' ? '✓ success' : h.status === 'pending' ? '⏳ pending' : h.status === 'partial' ? '⚠ partial' : '✗ ' + h.status;
        const stColor = h.status === 'success' ? 'var(--ok-fg)' : h.status === 'pending' ? 'var(--muted)' : 'var(--bad-fg)';
        html += '<tr style="border-bottom: 1px solid var(--border);">';
        html += '<td style="padding: 6px; color: var(--muted);">' + timeAgo(h.timestamp) + '</td>';
        html += '<td style="padding: 6px; font-weight: 500;">v' + escapeHtml(h.version) + (h.rollback ? ' (rollback)' : '') + '</td>';
        html += '<td style="padding: 6px; color: var(--muted);">v' + escapeHtml(h.fromVersion || '?') + '</td>';
        html += '<td style="padding: 6px;"><span style="color: ' + stColor + ';">' + st + '</span></td>';
        html += '</tr>';
        if (h.error) {
          html += '<tr><td colspan="4" style="padding: 4px 6px 8px; font-size: 0.78rem; color: var(--bad-fg);">' + escapeHtml(h.error) + '</td></tr>';
        }
        if (h.note) {
          html += '<tr><td colspan="4" style="padding: 4px 6px 8px; font-size: 0.78rem; color: var(--muted);">' + escapeHtml(h.note) + '</td></tr>';
        }
      }
      html += '</table>';
      dcHistoryContainer.innerHTML = html;
    } catch (e) {
      dcHistoryContainer.innerHTML = '<div class="panel-empty" style="color: var(--bad-fg);">Failed: ' + escapeHtml(e.message) + '</div>';
    }
  }

  async function dcShowRollback() {
    try {
      const res = await fetch('/api/v1/system/rollback-versions');
      const data = await res.json();
      const versions = data.success && data.versions ? data.versions : [];
      if (versions.length === 0) {
        showNotification('No rollback versions available.', 'info');
        return;
      }
      const version = prompt('Available rollback versions:\n' + versions.join('\n') + '\n\nEnter version to rollback to:');
      if (!version) return;
      if (!versions.includes(version)) {
        showNotification('Invalid version: ' + version, 'error');
        return;
      }
      if (!confirm('Rollback DashCaddy to v' + version + '? The container will restart.')) return;
      dcShowStatus('Rolling back to v' + version + '...', 'info');
      const r = await secureFetch('/api/v1/system/rollback', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ version })
      });
      const d = await r.json();
      if (d.success) {
        dcShowStatus('Rollback to v' + version + ' initiated. Container will restart.', 'success');
      } else {
        throw new Error(d.error || 'Rollback failed');
      }
    } catch (e) {
      dcShowStatus('Rollback failed: ' + e.message, 'error');
    }
  }

  dcCheckBtn?.addEventListener('click', () => dcCheckForUpdate(false));
  dcApplyBtn?.addEventListener('click', () => dcApplyUpdate().catch(() => {}));
  dcRollbackBtn?.addEventListener('click', dcShowRollback);

  checkBtn?.addEventListener('click', checkForUpdates);
  openBtn?.addEventListener('click', () => {
    modal?.classList.add('show');
    loadAvailable();
  });
  wireModal(modal, cancelBtn);

  // Open Update Management modal, optionally scrolled to a specific app
  window.openUpdateModal = function(appId) {
    modal?.classList.add('show');
    loadAvailable().then(() => {
      if (!appId) return;
      // Scroll to and highlight the matching row
      const row = availableContainer.querySelector(`[data-app-id="${appId}"]`);
      if (row) {
        row.scrollIntoView({ behavior: 'smooth', block: 'center' });
        row.style.background = 'rgba(249,115,22,0.15)';
        setTimeout(() => { row.style.background = ''; }, 3000);
      }
    });
  };

  // Lazy-load tabs
  document.querySelector('[data-panel="updates-history"]')?.addEventListener('click', loadHistory);
  document.querySelector('[data-panel="updates-auto"]')?.addEventListener('click', loadAutoConfig);
  document.querySelector('[data-panel="updates-dashcaddy"]')?.addEventListener('click', () => {
    dcLoadVersion();
    dcLoadHistory();
    if (!dcLastCheck) dcCheckForUpdate(true);
  });

  window.dcApplyUpdate = dcApplyUpdate;
  window.dcCheckForUpdate = dcCheckForUpdate;

  // Non-blocking check on page load — just adds notification dot if update available
  setTimeout(() => dcCheckForUpdate(true), 5000);
})();
