// dashboard-signals-view.js — extracted verbatim from dashboard.js (pure move).

// ── Signals view ─────────────────────────────────────────────────

let signalsFilter = { status: "new", platform: "" };

// Map contextAccount.platform → the platform value the signals filter expects.
// Most are 1:1 except "smtp" (no email signals — we leave platform unfiltered).
function signalsPlatformForContext(ctx) {
  if (!ctx) return "";
  if (ctx.platform === "smtp") return "";
  return ctx.platform; // twitter / linkedin / telegram match directly
}

async function renderSignals() {
  // If the top-bar account picker is set to a platform we monitor signals on,
  // override the platform filter so the page shows only that platform's signals.
  // The user can still flip the dropdown manually \u2014 we don't lock it.
  const ctxPlatform = signalsPlatformForContext(dashboardState.contextAccount);
  if (ctxPlatform && signalsFilter.platform !== ctxPlatform) {
    signalsFilter.platform = ctxPlatform;
  }

  const content = el("div", {}, [
    el("div", { class: "page-header" }, [
      el("div", {}, [
        el("div", { class: "page-title" }, "Buying Signals"),
        el(
          "div",
          { class: "page-subtitle" },
          "Posts matching your keywords \u2014 pursue with contextual outreach",
        ),
      ]),
      el("div", { style: "display: flex; gap: 8px;" }, [
        el(
          "button",
          { class: "btn btn-primary", type: "button", onclick: () => showKeywordsDrawer() },
          "\u2795 Manage Keywords",
        ),
      ]),
    ]),

    // \u2500\u2500 One-shot setup from a website URL \u2500\u2500
    // Paste the user's site \u2192 backend infers their services + auto-seeds keywords.
    // Renders inline so first-time users see it before the search/list cards.
    el(
      "div",
      {
        class: "card",
        id: "signals-setup-card",
        style: "margin-bottom: 16px;border-left:3px solid var(--accent, #4a90e2);",
      },
      [
        el("div", { class: "card-title" }, "\u2728 Set up from your website"),
        el(
          "div",
          { class: "muted small", style: "margin-bottom: 8px;" },
          "Paste your homepage URL. The bot reads the site, infers the services you sell, and auto-generates the search keywords used by every scanner (Twitter, LinkedIn, Reddit, HackerNews).",
        ),
        el("div", { style: "display: flex; gap: 8px; align-items: stretch;" }, [
          el("input", {
            class: "filter-input",
            id: "signals-setup-url-input",
            placeholder: "https://your-company.io",
            style: "flex:1;min-width: 240px;",
            onkeydown: (e) => {
              if (e.key === "Enter") runSignalsSetupFromUrl();
            },
          }),
          el(
            "button",
            {
              class: "btn btn-primary",
              type: "button",
              id: "signals-setup-btn",
              onclick: () => runSignalsSetupFromUrl(),
            },
            "Analyse \u2192",
          ),
        ]),
        el("div", { id: "signals-setup-status", class: "muted small", style: "margin-top: 8px;" }),
      ],
    ),

    // Live search
    el("div", { class: "card", style: "margin-bottom: 16px;" }, [
      el("div", { class: "card-title" }, "\ud83d\udd0d Search People & Posts"),
      el("div", { style: "display: flex; gap: 8px; align-items: flex-end;" }, [
        el("div", { style: "flex: 1;" }, [
          el("input", {
            class: "filter-input",
            id: "signal-search-input",
            placeholder: "Search: hiring crypto, market making, Paris blockchain week\u2026",
            style: "min-width: 100%;",
            onkeydown: (e) => {
              if (e.key === "Enter") runSignalSearch();
            },
          }),
        ]),
        el("select", { class: "filter-select", id: "signal-search-platform" }, [
          el("option", { value: "linkedin" }, "LinkedIn"),
          el("option", { value: "twitter" }, "Twitter/X"),
          el("option", { value: "reddit" }, "Reddit"),
          el("option", { value: "hackernews" }, "HackerNews"),
          el("option", { value: "all" }, "All platforms"),
        ]),
        el(
          "button",
          { class: "btn btn-primary", type: "button", onclick: () => runSignalSearch() },
          "\ud83d\udd0d Search",
        ),
      ]),
      el("div", { id: "signal-search-results", style: "margin-top: 12px;" }),
    ]),

    el("div", { class: "filter-row" }, [
      el(
        "select",
        {
          class: "filter-select",
          onchange: (e) => {
            signalsFilter.status = e.target.value;
            loadSignals();
          },
        },
        [
          optionEl("new", "New", signalsFilter.status),
          optionEl("pursuing", "Pursuing", signalsFilter.status),
          optionEl("dismissed", "Dismissed", signalsFilter.status),
          optionEl("all", "All", signalsFilter.status),
        ],
      ),
      el(
        "select",
        {
          class: "filter-select",
          onchange: (e) => {
            signalsFilter.platform = e.target.value;
            loadSignals();
          },
        },
        [
          optionEl("", "All platforms", signalsFilter.platform),
          optionEl("linkedin", "LinkedIn", signalsFilter.platform),
          optionEl("twitter", "Twitter/X", signalsFilter.platform),
          optionEl("reddit", "Reddit", signalsFilter.platform),
          optionEl("hackernews", "HackerNews", signalsFilter.platform),
          optionEl("telegram", "Telegram", signalsFilter.platform),
        ],
      ),
    ]),
    el("div", { id: "signals-list-wrap" }, [el("div", { class: "loading" }, "Loading signals…")]),
  ]);
  content.insertBefore(_discoverHubNav("signals"), content.children[1] || null);
  setContentNode(content);
  await loadSignals();
}

function optionEl(value, label, selected) {
  const o = el("option", { value }, label);
  if (value === selected) o.setAttribute("selected", "selected");
  return o;
}

async function loadSignals() {
  const wrap = $("#signals-list-wrap");
  if (!wrap) return;
  const qs = `?${new URLSearchParams({
    status: signalsFilter.status,
    ...(signalsFilter.platform && { platform: signalsFilter.platform }),
    limit: "100",
  }).toString()}`;
  const data = await api("signals-list", { queryString: qs });
  if (data?.error) {
    wrap.innerHTML = `<div class="empty-state"><div class="empty-state-title">Error</div><div class="empty-state-hint">${escapeHtml(data.error)}</div></div>`;
    return;
  }
  const signals = data?.signals || [];
  if (signals.length === 0) {
    wrap.innerHTML = `<div class="empty-state"><div class="empty-state-icon">🔥</div><div class="empty-state-title">No signals</div><div class="empty-state-hint">Add keywords and wait for the scanner to find matches</div></div>`;
    return;
  }

  wrap.innerHTML = "";
  for (const s of signals) {
    wrap.appendChild(renderSignalCard(s));
  }
}

function renderSignalCard(s) {
  const platformIcon =
    { linkedin: "\ud83d\udd17", twitter: "\ud83d\udc26", telegram: "\u2708\ufe0f" }[s.platform] ||
    "\u25cf";
  const urgencyColor =
    s.urgency === "high"
      ? "var(--red)"
      : s.urgency === "medium"
        ? "var(--yellow)"
        : "var(--text-4)";
  const confidence = s.ai_confidence ? `${Math.round(s.ai_confidence * 100)}%` : null;

  const card = el("div", { class: "card", style: `border-left: 3px solid ${urgencyColor};` });
  card.appendChild(
    el("div", { class: "row", style: "justify-content: space-between; gap: 16px;" }, [
      el("div", { class: "grow", style: "min-width: 0;" }, [
        el("div", { class: "row", style: "gap: 8px; margin-bottom: 4px;" }, [
          el("span", {}, platformIcon),
          el("span", { class: "primary-cell" }, s.source_handle || "(unknown)"),
          s.source_company
            ? el("span", { class: "muted small" }, `\u00b7 ${s.source_company}`)
            : null,
          confidence ? el("span", { class: "badge badge-purple" }, confidence) : null,
        ]),
        el(
          "div",
          { class: "muted small", style: "margin-bottom: 4px;" },
          `Matched: "${s.matched_keyword || "?"}" \u00b7 ${fmtDate(s.created_at)}`,
        ),
        el(
          "div",
          { class: "muted truncate", style: "font-size: 12px; line-height: 1.5;" },
          (s.source_text || "").slice(0, 200),
        ),
      ]),
      el("div", { style: "display: flex; gap: 6px; flex-shrink: 0; align-items: flex-start;" }, [
        s.status === "new"
          ? el(
              "button",
              {
                class: "btn btn-primary btn-tiny",
                onclick: () => navigate(`signals/pursue/${s.id}`),
              },
              "\ud83c\udfaf Pursue",
            )
          : el("span", { class: "badge badge-gray" }, s.status),
        s.status === "new"
          ? el(
              "button",
              {
                class: "btn btn-secondary btn-tiny",
                onclick: async () => {
                  const r = await api("signal-dismiss", { signalId: s.id });
                  if (r?.ok) {
                    toast("Dismissed", "ok");
                    loadSignals();
                  } else toast(`Error: ${r?.error || "failed"}`, "err");
                },
              },
              "\u00d7",
            )
          : null,
      ]),
    ]),
  );
  return card;
}

async function showKeywordsDrawer() {
  const data = await api("signals-keywords-list");
  const keywords = data?.keywords || [];
  const body = el("div", {}, [
    el("h4", {}, "Add keyword"),
    el("div", { class: "row", style: "gap: 6px;" }, [
      el("select", { id: "kw-platform", class: "filter-select" }, [
        el("option", { value: "all" }, "All platforms"),
        el("option", { value: "twitter" }, "Twitter"),
        el("option", { value: "linkedin" }, "LinkedIn"),
        el("option", { value: "telegram" }, "Telegram"),
      ]),
      el("input", { id: "kw-input", class: "filter-input", placeholder: "e.g. hiring web3 bd" }),
      el(
        "button",
        {
          class: "btn btn-primary",
          onclick: async () => {
            const platform = $("#kw-platform").value;
            const keyword = $("#kw-input").value.trim();
            if (keyword.length < 3) return toast("Keyword must be at least 3 chars", "err");
            const r = await api("signals-keywords-add", { body: { platform, keyword } });
            if (r?.ok) {
              toast("Added", "ok");
              showKeywordsDrawer();
            } else toast(`Error: ${r?.error || "failed"}`, "err");
          },
        },
        "Add",
      ),
    ]),
    el("h4", {}, "Active keywords"),
    keywords.length === 0
      ? el("div", { class: "muted small" }, "No keywords yet")
      : el(
          "div",
          {},
          keywords.map((k) =>
            el("div", { class: "field-row" }, [
              el("div", {}, [
                el("span", { class: "badge badge-gray", style: "margin-right: 6px;" }, k.platform),
                el("span", {}, k.keyword),
                k.hit_count ? el("span", { class: "muted small" }, ` · ${k.hit_count} hits`) : null,
              ]),
              el(
                "button",
                {
                  class: "btn btn-tiny btn-danger",
                  onclick: async () => {
                    const r = await api("signals-keywords-delete", { keywordId: k.id });
                    if (r?.ok) {
                      toast("Removed", "ok");
                      showKeywordsDrawer();
                    } else toast(`Error: ${r?.error || "failed"}`, "err");
                  },
                },
                "×",
              ),
            ]),
          ),
        ),
  ]);
  openDrawer("Signal keywords", body);
}

let searchResults = [];
let searchSelected = new Set();

// One-shot setup: paste website URL → bot infers services + auto-seeds keywords.
// Backend (handleSetupFromUrl) chains scrapeWebsiteContent → generateServicesFromWebsite
// → analyzeServiceProfile → saveServiceProfile → seedKeywordsFromServiceProfile.
async function runSignalsSetupFromUrl() {
  const input = document.getElementById("signals-setup-url-input");
  const btn = document.getElementById("signals-setup-btn");
  const status = document.getElementById("signals-setup-status");
  if (!input || !btn) return;

  const url = String(input.value || "").trim();
  if (!url || !/^https?:\/\/|^[a-z0-9.-]+\.[a-z]{2,}/i.test(url)) {
    toast("Enter a valid URL (e.g. https://your-site.io)", "err");
    return;
  }

  btn.disabled = true;
  const originalLabel = btn.textContent;
  btn.textContent = "⏳ Analysing…";
  if (status)
    status.textContent =
      "Reading your site, inferring services, generating keywords… this takes 5–15s.";

  try {
    const r = await api("signals-setup-from-url", { body: { url } });
    if (r?.error) {
      toast(`❌ ${r.error}`, "err");
      if (status) status.textContent = "Failed: " + r.error;
      return;
    }
    const services = (r.services || []).map((s) => s.name).filter(Boolean);
    const cats = (r.profile?.matched_categories || []).join(", ");
    const seeded = r.keywordsSeeded || 0;
    toast(`✅ Seeded ${seeded} keywords from your site`, "ok");
    if (status) {
      status.innerHTML =
        `<b>${escapeHtml(r.websiteTitle || "Site")}</b> — ${escapeHtml(r.websiteSummary || "")}<br>` +
        `<b>Services found:</b> ${escapeHtml(services.join(", ") || "—")}<br>` +
        `<b>Categories:</b> ${escapeHtml(cats || "—")}<br>` +
        `<b>Keywords seeded:</b> ${seeded}` +
        (r.cached ? ' <span class="muted">(cached — pass force=true to re-run)</span>' : "");
    }
    // Refresh the signals list and the keyword drawer if open.
    await loadSignals();
  } catch (err) {
    toast(`❌ ${err.message || "Network error — reload the extension"}`, "err");
    if (status) status.textContent = "Failed: " + (err.message || "network error");
  } finally {
    btn.disabled = false;
    btn.textContent = originalLabel;
  }
}

async function runSignalSearch() {
  const query = document.getElementById("signal-search-input")?.value?.trim();
  const platform = document.getElementById("signal-search-platform")?.value || "linkedin";
  const wrap = document.getElementById("signal-search-results");
  if (!wrap) return;
  if (!query || query.length < 2) {
    toast("Enter a search query (min 2 chars)", "err");
    return;
  }

  wrap.innerHTML = '<div class="loading" style="padding: 12px;">Searching\u2026</div>';
  const data = await api("signals-search", { body: { query, platform } }).catch(() => ({}));
  searchResults = (data?.results || []).map((r, i) => ({ ...r, _idx: i }));
  searchSelected = new Set(searchResults.map((_, i) => i)); // select all by default

  if (searchResults.length === 0) {
    wrap.innerHTML =
      '<div class="muted small" style="padding: 8px;">No results found. Try different keywords or check your sessions.</div>';
    return;
  }

  renderSearchResults(wrap, query);
}

function renderSearchResults(wrap, query) {
  wrap.innerHTML = "";
  const platformIcons = { linkedin: "\ud83d\udd17", twitter: "\ud83d\udc26" };
  const selectedCount = searchSelected.size;

  // Bulk action bar
  const bulkBar = el(
    "div",
    {
      style:
        "display: flex; gap: 8px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--border); flex-wrap: wrap;",
    },
    [
      el(
        "label",
        {
          style:
            "display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text-2); cursor: pointer;",
        },
        [
          el("input", {
            type: "checkbox",
            checked: selectedCount === searchResults.length,
            onchange: (e) => {
              if (e.target.checked) searchResults.forEach((_, i) => searchSelected.add(i));
              else searchSelected.clear();
              renderSearchResults(wrap, query);
            },
          }),
          `${selectedCount}/${searchResults.length} selected`,
        ],
      ),
      selectedCount > 0
        ? el(
            "button",
            {
              class: "btn btn-tiny btn-primary",
              type: "button",
              onclick: (e) => engageSelected(e.target, query, "connect"),
            },
            `\ud83d\udd17 Connect ${selectedCount}`,
          )
        : null,
      selectedCount > 0
        ? el(
            "button",
            {
              class: "btn btn-tiny btn-secondary",
              type: "button",
              onclick: (e) => engageSelected(e.target, query, "like"),
            },
            `\u2764 Like ${selectedCount}`,
          )
        : null,
      selectedCount > 0
        ? el(
            "button",
            {
              class: "btn btn-tiny btn-secondary",
              type: "button",
              onclick: (e) => engageSelected(e.target, query, "comment"),
            },
            `\ud83d\udcac AI Comment ${selectedCount}`,
          )
        : null,
      selectedCount > 0
        ? el(
            "button",
            {
              class: "btn btn-tiny btn-secondary",
              type: "button",
              onclick: (e) => engageSelected(e.target, query, "save"),
            },
            `\ud83d\udcc5 Save ${selectedCount} to CRM`,
          )
        : null,
    ],
  );
  wrap.appendChild(bulkBar);

  // Individual results
  for (const r of searchResults) {
    const isSelected = searchSelected.has(r._idx);
    const row = el(
      "div",
      {
        style: `display: flex; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px solid rgba(28,28,38,0.3); font-size: 12px; opacity: ${isSelected ? 1 : 0.5};`,
      },
      [
        el("input", {
          type: "checkbox",
          checked: isSelected,
          onchange: (e) => {
            if (e.target.checked) searchSelected.add(r._idx);
            else searchSelected.delete(r._idx);
            renderSearchResults(wrap, query);
          },
        }),
        el("span", { style: "font-size: 14px;" }, platformIcons[r.platform] || "\u2022"),
        el("div", { style: "flex: 1; min-width: 0;" }, [
          el("div", { class: "primary-cell" }, r.name || r.handle || "Unknown"),
          r.title
            ? el(
                "div",
                {
                  class: "muted",
                  style:
                    "font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;",
                },
                r.title,
              )
            : null,
          r.company ? el("div", { class: "muted", style: "font-size: 10px;" }, r.company) : null,
          r.tweetText
            ? el(
                "div",
                { class: "muted", style: "font-size: 11px; margin-top: 3px; line-height: 1.4;" },
                r.tweetText,
              )
            : null,
        ]),
        r.url
          ? el(
              "button",
              {
                class: "btn btn-tiny btn-secondary",
                type: "button",
                onclick: () => window.open(r.url, "_blank"),
              },
              "\u2197",
            )
          : null,
      ],
    );
    wrap.appendChild(row);
  }
  wrap.appendChild(
    el(
      "div",
      { class: "muted small", style: "padding: 8px 0;" },
      `${searchResults.length} results for "${query}"`,
    ),
  );
}

async function engageSelected(btn, query, action) {
  const selected = searchResults.filter((_, i) => searchSelected.has(i));
  if (selected.length === 0) {
    toast("Select at least one result", "err");
    return;
  }

  await withProgress(btn, async () => {
    let ok = 0,
      fail = 0;
    for (const r of selected) {
      try {
        const { token, apiBase } = await chrome.storage.local.get(["token", "apiBase"]);
        const base = (apiBase || "http://localhost:9091").replace(/\/$/, "");

        if (action === "connect" && r.platform === "linkedin") {
          await fetch(`${base}/api/twitter/command`, {
            method: "POST",
            headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
            body: JSON.stringify({
              type: "linkedin:http-send-connection",
              params: { publicIdentifier: r.handle },
            }),
          });
          ok++;
        } else if (action === "connect" && r.platform === "twitter") {
          await fetch(`${base}/api/twitter/command`, {
            method: "POST",
            headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
            body: JSON.stringify({
              type: "twitter:http-follow-by-username",
              params: { targetUsername: r.handle },
            }),
          });
          ok++;
        } else if (action === "like" && r.tweetId) {
          await fetch(`${base}/api/twitter/command`, {
            method: "POST",
            headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
            body: JSON.stringify({ type: "twitter:http-like", params: { tweetId: r.tweetId } }),
          });
          ok++;
        } else if (action === "like" && r.platform === "linkedin") {
          // LinkedIn like needs a postUrn — skip if we don't have posts
          toast(`Like not available for ${r.name} (no post)`, "info");
        } else if (action === "comment") {
          // Generate AI comment and post it
          const name = r.name?.split(" ")[0] || "";
          const comment = r.tweetText
            ? `Great point, ${name}! This resonates with what we\u2019re seeing in the space.`
            : `Interesting work at ${r.company || "your company"}, ${name}! Would love to connect and explore synergies.`;

          if (r.tweetId && r.platform === "twitter") {
            await fetch(`${base}/api/twitter/command`, {
              method: "POST",
              headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
              body: JSON.stringify({
                type: "twitter:http-reply",
                params: { text: comment, replyToTweetId: r.tweetId },
              }),
            });
            ok++;
          } else if (r.platform === "linkedin" && r.handle) {
            // For LinkedIn people results, send connection with note instead
            await fetch(`${base}/api/twitter/command`, {
              method: "POST",
              headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
              body: JSON.stringify({
                type: "linkedin:http-send-connection",
                params: { publicIdentifier: r.handle, note: comment },
              }),
            });
            ok++;
          }
        } else if (action === "save") {
          const syncBody = {
            platform: r.platform,
            identifier: r.handle || r.name,
            displayName: r.name,
            source: `search:${query}`,
          };
          if (r.platform === "linkedin" && r.url) syncBody.linkedinUrl = r.url;
          if (r.platform === "twitter") syncBody.twitterHandle = r.handle;
          await api("connect-account", { body: { platform: "crm_sync", ...syncBody } }).catch(
            () => {},
          );
          ok++;
        }

        // Rate limit delay between actions
        if (selected.length > 1) await new Promise((res) => setTimeout(res, 2000));
      } catch {
        fail++;
      }
    }
    toast(`\u2705 ${ok} succeeded${fail > 0 ? `, ${fail} failed` : ""}`, ok > 0 ? "ok" : "err");
  });
}
