// ── State ─────────────────────────────────────────────────────────────
let token = null;
let apiBase = null;
let liCookies = null;
let twCookies = null;
let authMode = "login"; // "login" | "register"

const API_TIMEOUT = 15000;

// Cookie mapper — mirrors background.js:7. Inlined because popup and
// service worker are separate execution contexts; the popup can't call
// helpers defined in the service worker.
function mapChromeCookie(c) {
  return {
    name: c.name, value: c.value, domain: c.domain, path: c.path,
    secure: c.secure, httpOnly: c.httpOnly,
    sameSite: c.sameSite === "no_restriction" ? "None"
           : c.sameSite === "lax" ? "Lax"
           : c.sameSite === "strict" ? "Strict" : "None",
    ...(c.expirationDate ? { expires: c.expirationDate } : {}),
  };
}

// ── Init ──────────────────────────────────────────────────────────────
document.addEventListener("DOMContentLoaded", async () => {
  const saved = await chrome.storage.local.get(["token", "apiBase"]);
  token = saved.token || null;
  apiBase = saved.apiBase || null;

  if (!token) {
    showScreen("pair");
  } else {
    showScreen("main");
    await detectCookies();
    loadStatus();
    loadStrategies();
    refreshBgmode();
    refreshTgAddon();
    setInterval(loadStatus, 60000);
    setInterval(loadStrategies, 30000); // Refresh strategies every 30s
    setInterval(refreshBgmode, 15000);
  }

  // Pre-fill settings
  document.getElementById("s-token").value = token || "";
  document.getElementById("s-api").value = apiBase || "http://localhost:9091";

  // Gear toggle
  document.getElementById("gear-btn").addEventListener("click", () => {
    const sp = document.getElementById("settings-panel");
    const showing = !sp.classList.contains("hidden");
    if (showing) {
      showScreen(token ? "main" : "pair");
    } else {
      showScreen("settings");
    }
  });

  // Open Dashboard — full-page UI in new tab
  const dashBtn = document.getElementById("open-dashboard-btn");
  if (dashBtn) {
    dashBtn.addEventListener("click", () => {
      chrome.tabs.create({ url: chrome.runtime.getURL("dashboard.html") });
      window.close();
    });
  }

  // ── Web auth (login / register) ──────────────────────────────────
  document.getElementById("tab-login")?.addEventListener("click", () => setAuthMode("login"));
  document.getElementById("tab-register")?.addEventListener("click", () => setAuthMode("register"));
  document.getElementById("auth-btn")?.addEventListener("click", doAuth);
  document.getElementById("wallet-connect-btn")?.addEventListener("click", doWalletConnect);
  document.getElementById("auth-password")?.addEventListener("keydown", (e) => {
    if (e.key === "Enter") doAuth();
  });

  // ── Pairing (legacy / optional Telegram path) ────────────────────
  document.getElementById("pair-btn").addEventListener("click", doPair);
  document.getElementById("pair-code").addEventListener("keydown", (e) => {
    if (e.key === "Enter") doPair();
  });

  // ── Telegram add-on (link via /pair code from inside the app) ─────
  document.getElementById("tg-link-btn")?.addEventListener("click", doTgLink);
  document.getElementById("tg-link-code")?.addEventListener("keydown", (e) => {
    if (e.key === "Enter") doTgLink();
  });

  // ── Save settings (manual token entry) ───────────────────────────
  document.getElementById("save-settings-btn").addEventListener("click", async () => {
    const t = document.getElementById("s-token").value.trim();
    const a = document.getElementById("s-api").value.trim();
    if (!t) return showToast("s-toast", "Token is required", false);
    await chrome.storage.local.set({ token: t, apiBase: a || "http://localhost:9091" });
    token = t;
    apiBase = a || "http://localhost:9091";
    showToast("s-toast", "Settings saved!", true);
    setTimeout(() => { showScreen("main"); detectCookies(); loadStatus(); }, 800);
  });

  // ── Disconnect ───────────────────────────────────────────────────
  document.getElementById("disconnect-btn").addEventListener("click", async () => {
    // Best-effort server-side token revocation (logout), then clear locally.
    try {
      if (token) {
        const base = (apiBase || "http://localhost:9091").replace(/\/$/, "");
        await fetch(`${base}/api/auth/logout`, {
          method: "POST",
          headers: { "Authorization": `Bearer ${token}` },
          signal: AbortSignal.timeout(5000),
        }).catch(() => {});
      }
    } catch { /* ignore — local clear still proceeds */ }
    await chrome.storage.local.remove(["token", "apiBase", "walletAddress"]);
    token = null;
    apiBase = null;
    showScreen("pair");
  });

  // ── Full reset ───────────────────────────────────────────────────
  // Three entry points share doFullReset(): the settings button, the
  // pair-screen "Having trouble?" link, and the SW-not-responding banner.
  document.getElementById("reset-btn")?.addEventListener("click", doFullReset);
  document.getElementById("pair-reset-link")?.addEventListener("click", doFullReset);
  document.getElementById("sw-warning-reset")?.addEventListener("click", doFullReset);

  // ── Service-worker health check ──────────────────────────────────
  // Ping the SW; if it can't be reached, surface the reset banner so a
  // wedged worker (the "No SW" failure mode) is recoverable in one click.
  checkServiceWorker();

  // Sync buttons
  document.getElementById("li-sync-btn").addEventListener("click", syncLinkedIn);
  document.getElementById("tw-sync-btn").addEventListener("click", syncTwitter);
  document.getElementById("wallet-link-btn")?.addEventListener("click", linkWalletConnect);

  // Status refresh
  document.getElementById("refresh-status-btn").addEventListener("click", loadStatus);

  // Background mode toggle — wires to the same SW handlers the floating
  // panel's Auto chip uses (li-autonomous-enable / -disable). Both UIs
  // stay in sync because they read state from chrome.storage.local.
  document.getElementById("bgmode-toggle-btn").addEventListener("click", onBgmodeToggle);

  // Advanced toggle on pairing screen
  document.getElementById("advanced-toggle")?.addEventListener("click", () => {
    const section = document.getElementById("advanced-section");
    if (section) section.classList.toggle("hidden");
  });
});

// ── Screen management ─────────────────────────────────────────────────
function showScreen(screen) {
  document.getElementById("pair-screen").classList.toggle("hidden", screen !== "pair");
  document.getElementById("main-ui").classList.toggle("hidden", screen !== "main");
  document.getElementById("settings-panel").classList.toggle("hidden", screen !== "settings");
}

// ── Full reset / SW health ────────────────────────────────────────────
// Wipes ALL extension state and restarts the extension (respawns the
// service worker). Recovery path for a wedged SW ("No SW") or stuck pairing.
async function doFullReset() {
  if (!confirm("Reset the extension?\n\nThis clears ALL stored data (login, settings, cached sessions) and restarts it. You'll need to log in or pair again.")) return;
  try { await chrome.storage.local.clear(); } catch { /* ignore */ }
  try { await chrome.storage.session?.clear?.(); } catch { /* session area may be unavailable */ }
  token = null;
  apiBase = null;
  // Restart the extension (respawns the service worker). Closes the popup.
  try { chrome.runtime.reload(); } catch { window.close(); }
}

// Ping the service worker; show the recovery banner if it doesn't answer.
async function checkServiceWorker() {
  const banner = document.getElementById("sw-warning");
  if (!banner) return;
  const res = await sendMsg({ type: "li-build-version" });
  // sendMsg resolves {error} on lastError, {} on no/empty response. A live SW
  // returns {build}. Anything without a build means the worker isn't answering.
  if (!res || !res.build) banner.classList.add("show");
  else banner.classList.remove("show");
}

// ── Pairing flow ──────────────────────────────────────────────────────
async function doPair() {
  const url = document.getElementById("pair-url").value.trim() || "https://nexus-bot.fly.dev";
  const code = document.getElementById("pair-code").value.trim();
  if (!code || code.length !== 6) return showToast("pair-toast", "Enter the 6-digit code from Telegram", false);

  const btn = document.getElementById("pair-btn");
  btn.disabled = true;
  btn.textContent = "Connecting...";

  try {
    const res = await fetch(`${url.replace(/\/$/, "")}/api/pair`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ code }),
    });
    const data = await res.json().catch(() => ({}));

    if (res.ok && data.success) {
      token = data.token;
      // Prefer the server-advertised public origin so a customer only needs a code.
      apiBase = (data.publicUrl || url).replace(/\/$/, "");
      await chrome.storage.local.set({ token, apiBase });
      showToast("pair-toast", "Paired successfully!", true);
      setTimeout(() => { showScreen("main"); detectCookies(); loadStatus(); }, 800);
    } else {
      const msg = (res.status === 400 || res.status === 404)
        ? "That code didn't work. Get a fresh one with /pair in your Nexus bot."
        : (res.status === 401 || res.status === 403)
        ? "That code expired. Run /pair again for a new one."
        : (data.error || `Couldn't pair (HTTP ${res.status}).`);
      showToast("pair-toast", msg, false);
    }
  } catch (err) {
    const isTimeout = /abort|timeout|failed to fetch/i.test(err.message || "");
    showToast("pair-toast", isTimeout
      ? `Can't reach the bot at ${url}. Make sure it's running — or set the Server URL under Advanced settings.`
      : `Network error: ${err.message}`, false);
  } finally {
    btn.disabled = false;
    btn.textContent = "Connect";
  }
}

// ── Web auth flow ──────────────────────────────────────────────────────
function setAuthMode(mode) {
  authMode = mode;
  document.getElementById("tab-login")?.classList.toggle("active", mode === "login");
  document.getElementById("tab-register")?.classList.toggle("active", mode === "register");
  const btn = document.getElementById("auth-btn");
  if (btn) btn.textContent = mode === "login" ? "Log in" : "Create account";
  const pw = document.getElementById("auth-password");
  if (pw) pw.setAttribute("autocomplete", mode === "login" ? "current-password" : "new-password");
}

async function doAuth() {
  const url = (document.getElementById("pair-url").value.trim() || "https://nexus-bot.fly.dev").replace(/\/$/, "");
  const email = document.getElementById("auth-email").value.trim();
  const password = document.getElementById("auth-password").value;
  if (!email || !password) return showToast("auth-toast", "Enter your email and password.", false);
  if (authMode === "register" && password.length < 8) return showToast("auth-toast", "Password must be at least 8 characters.", false);

  const btn = document.getElementById("auth-btn");
  btn.disabled = true;
  btn.textContent = authMode === "login" ? "Logging in…" : "Creating…";

  try {
    const res = await fetch(`${url}/api/auth/${authMode}`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email, password }),
      signal: AbortSignal.timeout(API_TIMEOUT),
    });
    const data = await res.json().catch(() => ({}));
    if (res.ok && data.token) {
      token = data.token;
      apiBase = url;
      await chrome.storage.local.set({ token, apiBase });
      showToast("auth-toast", authMode === "login" ? "Welcome back!" : "Account created!", true);
      setTimeout(() => { showScreen("main"); detectCookies(); loadStatus(); loadStrategies(); refreshBgmode(); refreshTgAddon(); }, 700);
    } else {
      showToast("auth-toast", data.message || data.error || `Couldn't ${authMode} (HTTP ${res.status}).`, false);
    }
  } catch (err) {
    const isTimeout = /abort|timeout|failed to fetch/i.test(err.message || "");
    showToast("auth-toast", isTimeout
      ? `Can't reach the server at ${url}. Make sure it's running — or set the Server URL under Advanced.`
      : `Network error: ${err.message}`, false);
  } finally {
    btn.disabled = false;
    btn.textContent = authMode === "login" ? "Log in" : "Create account";
  }
}

// ── Phantom / Solana wallet connect ────────────────────────────────────
// Phantom only injects into normal web pages, so the connect happens in a
// compact window served by the bot. The orchestration (open window → poll →
// store token / link) runs in the SERVICE WORKER, because this popup closes
// the instant that window takes focus — a popup-side poll would never finish.
// We just kick it off; the SW reports back via a "wallet-result" message, and
// the stored token is picked up when the popup is reopened.
async function doWalletConnect() {
  const url = (document.getElementById("pair-url").value.trim() || "http://localhost:9091").replace(/\/$/, "");
  await chrome.storage.local.set({ apiBase: url });
  chrome.runtime.sendMessage({ action: "wallet-connect-start", apiBase: url, mode: "login" });
  showToast("wallet-toast", "Approve in the Phantom window. You can reopen this popup once it's done.", true);
}

// Link a wallet to the ALREADY logged-in profile (vs. logging in fresh).
async function linkWalletConnect() {
  if (!token) return;
  chrome.runtime.sendMessage({ action: "wallet-connect-start", apiBase, mode: "link" });
  showToast("wallet-link-toast", "Approve in the Phantom window. You can reopen this popup once it's done.", true);
}

// The SW posts the outcome here. If the popup happens to still be open we
// reflect it live; otherwise reopening the popup reads the stored token.
chrome.runtime.onMessage.addListener((msg) => {
  if (msg?.type !== "wallet-result") return;
  if (msg.ok) {
    chrome.storage.local.get(["token", "apiBase", "walletAddress"]).then((s) => {
      token = s.token || token;
      apiBase = s.apiBase || apiBase;
      showToast(msg.linked ? "wallet-link-toast" : "wallet-toast", msg.linked ? "Wallet linked!" : "Wallet connected!", true);
      if (token) { showScreen("main"); detectCookies(); loadStatus(); }
    });
  } else {
    showToast("wallet-toast", msg.error || "Wallet connect failed.", false);
  }
});

// ── Telegram add-on (link + status) ────────────────────────────────────
async function refreshTgAddon() {
  const badge = document.getElementById("tg-addon-badge");
  const detail = document.getElementById("tg-addon-detail");
  const connect = document.getElementById("tg-addon-connect");
  if (!badge || !detail) return;
  try {
    const base = (apiBase || "http://localhost:9091").replace(/\/$/, "");
    const res = await fetch(`${base}/api/capabilities`, {
      headers: { "Authorization": `Bearer ${token}` },
      signal: AbortSignal.timeout(API_TIMEOUT),
    });
    const cap = await res.json().catch(() => ({}));
    if (!res.ok) { badge.textContent = "?"; badge.className = "card-badge"; detail.textContent = "Couldn't load add-on status."; return; }

    if (!cap.telegramEnabled) {
      badge.textContent = "Unavailable"; badge.className = "card-badge";
      detail.textContent = "No Telegram bot is configured on the server, so the add-on can't be connected. Everything else works without it.";
      if (connect) connect.classList.add("hidden");
    } else if (cap.telegramLinked) {
      badge.textContent = "Connected"; badge.className = "card-badge badge-green";
      detail.textContent = cap.hasPremiumAccount
        ? "Telegram is connected. DMs and Telegram-channel automations are available."
        : "Telegram is connected for notifications. Add a Telegram userbot account for group automations.";
      if (connect) connect.classList.add("hidden");
    } else {
      badge.textContent = "Not connected"; badge.className = "card-badge badge-yellow";
      detail.textContent = "Optional. Connect Telegram to also receive DM alerts and unlock Telegram-channel automations. Send /pair to your Nexus bot for a code.";
      if (connect) connect.classList.remove("hidden");
    }
  } catch {
    badge.textContent = "?"; badge.className = "card-badge";
    detail.textContent = "Couldn't load add-on status.";
  }
}

async function doTgLink() {
  const code = document.getElementById("tg-link-code").value.trim();
  if (!code || code.length !== 6) return showToast("tg-addon-toast", "Enter the 6-digit code from /pair.", false);
  const btn = document.getElementById("tg-link-btn");
  btn.disabled = true;
  btn.textContent = "Connecting…";
  try {
    const base = (apiBase || "http://localhost:9091").replace(/\/$/, "");
    const res = await fetch(`${base}/api/telegram/link`, {
      method: "POST",
      headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
      body: JSON.stringify({ code }),
      signal: AbortSignal.timeout(API_TIMEOUT),
    });
    const data = await res.json().catch(() => ({}));
    if (res.ok && data.ok) {
      showToast("tg-addon-toast", "Telegram connected!", true);
      document.getElementById("tg-link-code").value = "";
      refreshTgAddon();
    } else {
      showToast("tg-addon-toast", data.message || data.error || `Couldn't connect (HTTP ${res.status}).`, false);
    }
  } catch (err) {
    showToast("tg-addon-toast", `Network error: ${err.message}`, false);
  } finally {
    btn.disabled = false;
    btn.textContent = "Connect with /pair code";
  }
}

// ── Cookie Detection ───────────────────────────────────────────────────
async function detectCookies() {
  // LinkedIn
  const liAll = await chrome.cookies.getAll({ domain: ".linkedin.com" });
  const liAt = liAll.find(c => c.name === "li_at");
  const jsess = liAll.find(c => c.name === "JSESSIONID");

  const liBtn = document.getElementById("li-sync-btn");
  const liIcon = document.getElementById("li-badge-icon");
  if (liAt) {
    const email = liAll.find(c => c.name === "liap_email")?.value || null;
    const allCookies = liAll.map(mapChromeCookie);
    liCookies = { liAt: liAt.value, jsessionid: jsess ? jsess.value : "", email, allCookies };
    liIcon.textContent = "\u{1f7e2}";
    liBtn.disabled = false;
  } else {
    liCookies = null;
    liIcon.textContent = "\u{1f534}";
    liBtn.disabled = true;
  }

  // Twitter / X
  const twAll = [
    ...await chrome.cookies.getAll({ domain: ".twitter.com" }),
    ...await chrome.cookies.getAll({ domain: ".x.com" }),
  ];
  const authToken = twAll.find(c => c.name === "auth_token");
  const ct0 = twAll.find(c => c.name === "ct0");
  const twid = twAll.find(c => c.name === "twid") || twAll.find(c => c.name === "twid_u");

  const twBtn = document.getElementById("tw-sync-btn");
  const twIcon = document.getElementById("tw-badge-icon");
  if (authToken && ct0) {
    const numericId = twid ? decodeURIComponent(twid.value).replace(/^u%3D/, "").replace(/^u=/, "") : null;
    const username = numericId ? `tw_${numericId}` : `tw_unknown_${Date.now()}`;
    twCookies = { authToken: authToken.value, ct0: ct0.value, twid: twid?.value || null, username };
    twIcon.textContent = "\u{1f7e2}";
    twBtn.disabled = false;
  } else {
    twCookies = null;
    twIcon.textContent = "\u{1f534}";
    twBtn.disabled = true;
  }
}

// ── Connection Status ─────────────────────────────────────────────────
async function loadStatus() {
  const el = document.getElementById("status-content");
  el.innerHTML = '<span style="color:#666;font-size:11px;">Loading...</span>';

  // Update status banner — show "Connected" when status fetch starts; on error it'll flip to red.
  const banner = document.getElementById("status-banner");
  const bannerText = document.getElementById("status-banner-text");
  if (banner) banner.className = "status-banner green";
  if (bannerText) bannerText.textContent = "Connected";

  try {
    const base = (apiBase || "http://localhost:9091").replace(/\/$/, "");
    // Multi-tenant: reflect the active client workspace if one is selected.
    const { workspaceId, walletAddress } = await chrome.storage.local.get(["workspaceId", "walletAddress"]);
    const headers = { "Authorization": `Bearer ${token}` };
    if (workspaceId) headers["X-Workspace-Id"] = workspaceId;
    const res = await fetch(`${base}/api/connect/status`, {
      headers,
      signal: AbortSignal.timeout(API_TIMEOUT),
    });
    const data = await res.json();
    if (!res.ok) {
      el.innerHTML = `<span style="color:#f87171;font-size:11px;">${esc(data.error || "Failed")}</span>`;
      if (banner) banner.className = "status-banner red";
      if (bannerText) bannerText.textContent = "Bot error";
      return;
    }

    let html = "";

    // Wallet (if connected via Phantom) — the crypto address linked to this profile.
    if (walletAddress) {
      html += buildPlatformRow("\u{1f47b}", "Wallet", truncAddr(walletAddress), true, esc(walletAddress));
    }
    // Offer "Link a Solana wallet" only when none is linked yet.
    const linkBtn = document.getElementById("wallet-link-btn");
    if (linkBtn) linkBtn.classList.toggle("hidden", !!walletAddress);

    // Bot status
    html += buildPlatformRow("\u{1f916}", "Telegram Bot", "Paired", true);

    // LinkedIn
    const liSessions = data.linkedin || [];
    if (liSessions.length > 0) {
      for (const s of liSessions) {
        const detail = s.lastValidated ? `synced ${timeAgo(s.lastValidated)}` : "";
        html += buildPlatformRow("\u{1f517}", `LinkedIn: ${esc(s.identifier)}`, s.status === "active" ? "Active" : "Inactive", s.status === "active", detail);
      }
    } else {
      html += buildPlatformRow("\u{1f517}", "LinkedIn", "Ready to sync", false, "Log in to linkedin.com, then click Sync below");
    }

    // Twitter
    const twSessions = data.twitter || [];
    if (twSessions.length > 0) {
      for (const s of twSessions) {
        const detail = s.lastValidated ? `synced ${timeAgo(s.lastValidated)}` : "";
        html += buildPlatformRow("\u{1d54f}", `Twitter: @${esc(s.username)}`, s.status === "active" ? "Active" : "Inactive", s.status === "active", detail);
      }
    } else {
      html += buildPlatformRow("\u{1d54f}", "Twitter / X", "Ready to sync", false, "Log in to x.com, then click Sync below");
    }

    // Email
    const emailAccounts = data.email || [];
    if (emailAccounts.length > 0) {
      for (const s of emailAccounts) {
        html += buildPlatformRow("✉️", `Email: ${esc(s.email)}`, "Configured", true, esc(s.smtpHost));
      }
    } else {
      html += buildPlatformRow("✉️", "Email", "Not configured", false, "Configure in Dashboard → Accounts");
    }

    el.innerHTML = html;
  } catch (err) {
    el.innerHTML = `<span style="color:#f87171;font-size:11px;">Error: ${esc(err.message)}</span>`;
    if (banner) banner.className = "status-banner red";
    if (bannerText) bannerText.textContent = "Bot offline";
  }
}

function buildPlatformRow(icon, name, statusText, isOk, detail) {
  return `<div class="platform-row">
    <span class="platform-icon">${icon}</span>
    <div class="platform-info">
      <div class="platform-name">${name}</div>
      ${detail ? `<div class="platform-detail">${detail}</div>` : ""}
    </div>
    <span class="platform-status ${isOk ? "status-ok" : "status-none"}">${statusText}</span>
  </div>`;
}

// ── Sync Functions ─────────────────────────────────────────────────────
async function syncLinkedIn() {
  if (!liCookies) return;
  const btn = document.getElementById("li-sync-btn");
  btn.disabled = true;
  btn.textContent = "Syncing...";

  const result = await chrome.runtime.sendMessage({
    action: "connect",
    token,
    apiBase,
    body: {
      platform: "linkedin",
      liAt: liCookies.liAt,
      jsessionid: liCookies.jsessionid,
      identifier: liCookies.email || ("li_" + liCookies.liAt.slice(0, 16)),
      cookiesJson: JSON.stringify(liCookies.allCookies),
      userAgent: navigator.userAgent,
    },
  });

  if (result.success) {
    showToast("sync-toast", "LinkedIn synced!", true);
    loadStatus();
  } else {
    showToast("sync-toast", result.error || "LinkedIn sync failed", false);
  }
  btn.disabled = false;
  btn.innerHTML = `<span id="li-badge-icon">\u{1f7e2}</span> LinkedIn`;
}

async function syncTwitter() {
  if (!twCookies) return;
  const btn = document.getElementById("tw-sync-btn");
  btn.disabled = true;
  btn.textContent = "Syncing...";

  const result = await chrome.runtime.sendMessage({
    action: "connect",
    token,
    apiBase,
    body: {
      platform: "twitter",
      authToken: twCookies.authToken,
      ct0: twCookies.ct0,
      twid: twCookies.twid,
      username: twCookies.username,
    },
  });

  if (result.success) {
    showToast("sync-toast", "Twitter synced!", true);
    loadStatus();
  } else {
    showToast("sync-toast", result.error || "Twitter sync failed", false);
  }
  btn.disabled = false;
  btn.innerHTML = `<span id="tw-badge-icon">\u{1f7e2}</span> Twitter`;
}

// ── Helpers ───────────────────────────────────────────────────────────
function showToast(id, msg, ok) {
  const el = document.getElementById(id);
  el.textContent = msg;
  el.className = `toast show ${ok ? "ok" : "err"}`;
  setTimeout(() => { el.className = "toast"; }, 4000);
}

function esc(s) {
  const d = document.createElement("div");
  d.textContent = s || "";
  return d.innerHTML;
}

function truncAddr(a) {
  const s = String(a || "");
  return s.length > 12 ? `${s.slice(0, 4)}…${s.slice(-4)}` : s;
}

function timeAgo(isoStr) {
  if (!isoStr) return "never";
  const diffMs = Date.now() - new Date(isoStr).getTime();
  const diffH = Math.floor(diffMs / 3600000);
  if (diffH < 1) return "just now";
  if (diffH < 24) return `${diffH}h ago`;
  return `${Math.floor(diffH / 24)}d ago`;
}

// ── Strategy launcher card ─────────────────────────────────────────────

async function loadStrategies() {
  const listEl = document.getElementById("strategies-list");
  const badgeEl = document.getElementById("strategies-badge");
  if (!listEl) return;

  let data;
  try {
    data = await chrome.runtime.sendMessage({ action: "strategy-list" });
  } catch (err) {
    listEl.innerHTML = `<div class="strategy-empty">Error: ${err.message}</div>`;
    return;
  }
  if (data?.error) {
    listEl.innerHTML = `<div class="strategy-empty">${escapeHtml(data.error)}</div>`;
    return;
  }

  const strategies = data?.strategies || [];
  if (strategies.length === 0) {
    listEl.innerHTML = `<div class="strategy-empty">No strategies available</div>`;
    return;
  }

  const runningCount = strategies.filter(s => s.status?.running).length;
  if (badgeEl) {
    badgeEl.textContent = `${runningCount}/${strategies.length}`;
    badgeEl.className = "card-badge " + (runningCount > 0 ? "badge-green" : "");
  }

  listEl.innerHTML = strategies.map(s => renderStrategyRow(s)).join("");

  // Wire up event handlers
  for (const s of strategies) {
    if (s.type === "toggle") {
      const toggleEl = document.getElementById(`strat-toggle-${s.id}`);
      if (toggleEl) {
        toggleEl.addEventListener("click", () => handleStrategyToggle(s.id, !s.status?.running));
      }
    } else if (s.type === "launch") {
      const btn = document.getElementById(`strat-launch-${s.id}`);
      if (btn) btn.addEventListener("click", () => handleStrategyLaunch(s.id));
    } else if (s.type === "action") {
      const btn = document.getElementById(`strat-action-${s.id}`);
      if (btn) btn.addEventListener("click", () => handleStrategyAction(s.id));
    }
  }
}

function renderStrategyRow(s) {
  const statusLine = s.status?.running
    ? "\u{1f7e2} Running"
    : s.status?.needsSession
      ? "⚠️ Needs session"
      : "⚪ Idle";

  let actionHtml = "";
  if (s.type === "toggle") {
    actionHtml = `<div class="strategy-action"><div class="strategy-toggle${s.status?.running ? " on" : ""}" id="strat-toggle-${escapeHtml(s.id)}"></div></div>`;
  } else if (s.type === "launch") {
    actionHtml = `<div class="strategy-action"><button class="btn primary" id="strat-launch-${escapeHtml(s.id)}">Launch</button></div>`;
  } else if (s.type === "action") {
    actionHtml = `<div class="strategy-action"><button class="btn secondary" id="strat-action-${escapeHtml(s.id)}">Run</button></div>`;
  }

  return `
    <div class="strategy-row" data-strategy-id="${escapeHtml(s.id)}">
      <div class="strategy-icon">${s.icon || "•"}</div>
      <div class="strategy-body">
        <div class="strategy-name">${escapeHtml(s.name)}</div>
        <div class="strategy-desc">${escapeHtml(s.description)}</div>
        <div class="strategy-status-line">${statusLine}</div>
      </div>
      ${actionHtml}
    </div>
  `;
}

async function handleStrategyToggle(strategyId, enable) {
  const toast = document.getElementById("strategies-toast");
  try {
    const result = await chrome.runtime.sendMessage({
      action: "strategy-toggle",
      strategyId,
      enabled: enable,
    });
    if (result?.error) {
      showStrategyToast(`Error: ${result.error}`, "err");
    } else {
      showStrategyToast(`${enable ? "Enabled" : "Disabled"} ${strategyId}`, "ok");
      await loadStrategies(); // refresh
    }
  } catch (err) {
    showStrategyToast(`Error: ${err.message}`, "err");
  }
}

async function handleStrategyLaunch(strategyId) {
  try {
    const result = await chrome.runtime.sendMessage({
      action: "strategy-deeplink",
      strategyId,
    });
    if (result?.deeplink) {
      chrome.tabs.create({ url: result.deeplink });
    } else {
      showStrategyToast(`Error: ${result?.error || "no deeplink"}`, "err");
    }
  } catch (err) {
    showStrategyToast(`Error: ${err.message}`, "err");
  }
}

async function handleStrategyAction(strategyId) {
  // Build context from current tab (URL + any in-page data the popup can infer)
  let context = {};
  try {
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
    if (tab?.url) context.url = tab.url;
  } catch {}

  try {
    const result = await chrome.runtime.sendMessage({
      action: "strategy-action",
      strategyId,
      context,
    });
    if (result?.ok) {
      if (result.comment) {
        // ai_comment_current_post returns a generated comment — copy to clipboard
        try {
          await navigator.clipboard.writeText(result.comment);
          showStrategyToast(`✅ Comment copied to clipboard`, "ok");
        } catch {
          showStrategyToast(`✅ Generated: ${result.comment.slice(0, 40)}...`, "ok");
        }
      } else if (result.contactId) {
        showStrategyToast(result.deduped ? `✅ Already in CRM (#${result.contactId})` : `✅ Saved to CRM (#${result.contactId})`, "ok");
      } else {
        showStrategyToast(`✅ Done`, "ok");
      }
    } else {
      showStrategyToast(`❌ ${result?.error || "failed"}`, "err");
    }
  } catch (err) {
    showStrategyToast(`Error: ${err.message}`, "err");
  }
}

function showStrategyToast(text, kind = "ok") {
  const t = document.getElementById("strategies-toast");
  if (!t) return;
  t.textContent = text;
  t.className = `toast ${kind}`;
  t.style.display = "block";
  setTimeout(() => { t.style.display = "none"; }, 4000);
}

function escapeHtml(s) {
  return String(s ?? "")
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");
}

// ── Background mode pill ──────────────────────────────────────────────
// Surfaces two pieces of state:
//   1. Whether Autonomous Mode (the chrome.debugger CDP path) is enabled —
//      the only path that types into hidden / unfocused LinkedIn tabs.
//   2. Whether the dedicated worker tab is alive — that's the actual
//      hidden linkedin.com tab scheduled automations are driving.
//
// Both need to be ON for "automations run without focus" to be true.
async function refreshBgmode() {
  const badge = document.getElementById("bgmode-badge");
  const detail = document.getElementById("bgmode-detail");
  const btn = document.getElementById("bgmode-toggle-btn");
  if (!badge || !detail || !btn) return;

  let autonomous = false;
  let workerExists = false;
  try {
    const [autoRes, tabRes] = await Promise.all([
      sendMsg({ action: "li-autonomous-status" }),
      sendMsg({ action: "li-worker-tab-status" }),
    ]);
    autonomous = !!autoRes?.enabled;
    workerExists = !!tabRes?.exists;
  } catch { /* fall through to default off-state */ }

  btn.disabled = false;

  if (autonomous) {
    badge.className = "card-badge badge-green";
    badge.textContent = "ON";
    btn.textContent = "Disable";
    btn.className = "btn secondary";
    const tabLine = workerExists
      ? "Hidden worker tab is alive — scheduled actions are running there."
      : "No worker tab yet — one will spawn on the next scheduled run.";
    detail.textContent = `Background mode active. LinkedIn automations type into unfocused tabs via the debugger API. ${tabLine}`;
  } else {
    badge.className = "card-badge badge-yellow";
    badge.textContent = "OFF";
    btn.textContent = "Enable";
    btn.className = "btn primary";
    detail.textContent = "Off — LinkedIn DM / comment typing pauses when you switch away from the LinkedIn tab. Enable to let automations run in the background.";
  }
}

function sendMsg(payload) {
  return new Promise((resolve) => {
    try {
      chrome.runtime.sendMessage(payload, (r) => {
        const err = chrome.runtime.lastError;
        if (err) return resolve({ error: err.message });
        resolve(r || {});
      });
    } catch (err) { resolve({ error: err.message }); }
  });
}

async function onBgmodeToggle() {
  const btn = document.getElementById("bgmode-toggle-btn");
  const badge = document.getElementById("bgmode-badge");
  if (btn.disabled) return;
  const currentlyOn = badge.textContent === "ON";

  // Reading the chip state above is sync — we have not awaited anything,
  // so the user gesture is still alive when we sendMessage below. Same
  // gesture-preservation rule the floating panel chip uses.
  const action = currentlyOn ? "li-autonomous-disable" : "li-autonomous-enable";
  btn.disabled = true;
  btn.textContent = "…";

  const result = await sendMsg({ action });
  if (action === "li-autonomous-enable" && (result?.permissionDenied || result?.error)) {
    // Service worker's permission.request likely got rejected because the
    // gesture didn't propagate through the message channel. Fall back to
    // the dedicated grant page that has its own user-gesture context.
    showBgmodeToast("Opening permission page…", "ok");
    try {
      const grantUrl = chrome.runtime.getURL("autonomous-grant.html");
      chrome.tabs.create({ url: grantUrl, active: true });
    } catch (err) {
      showBgmodeToast(`Could not open grant page: ${err.message}`, "err");
    }
  } else if (action === "li-autonomous-enable" && result?.enabled) {
    showBgmodeToast("Background mode enabled.", "ok");
  } else if (action === "li-autonomous-disable") {
    showBgmodeToast("Background mode disabled.", "ok");
  } else if (result?.error) {
    showBgmodeToast(result.error, "err");
  }
  await refreshBgmode();
}

function showBgmodeToast(text, kind = "ok") {
  const t = document.getElementById("bgmode-toast");
  if (!t) return;
  t.textContent = text;
  t.className = `toast ${kind} show`;
  setTimeout(() => { t.className = "toast"; }, 3500);
}
