// screens-contacts.jsx — CRM: list + board views, lead drawer
const { useState } = React;
const STATUS_ORDER = ["new", "contacted", "replied", "interested", "proposal", "followup", "won", "lost"];

// Production-db.json compatibility: CRM statuses / stages (and a lead's own
// status/stage) may be stored as plain strings OR as objects ({key,label,...}).
// Rendering a raw object as a React child throws ("Objects are not valid as a
// React child") and crashed the Lead Drawer. Coerce safely to a string key/label.
const crmOptKey = (s) => (s && typeof s === "object" ? (s.key ?? s.value ?? s.id ?? s.name ?? "") : (s ?? ""));
const crmOptText = (s) => (s && typeof s === "object" ? (s.label ?? s.name ?? crmOptKey(s)) : s);
// AI-owned CRM intelligence display maps (Phase 1/3/4/5).
const SENTIMENT_TONE = { ready_to_buy: "green", excited: "green", interested: "lime", curious: "blue", price_sensitive: "orange", hesitant: "neutral", confused: "neutral", skeptical: "orange", frustrated: "orange", angry: "red", neutral: "neutral" };
const OBJECTION_LABEL = { price: "Price", seo_fear: "SEO/ranking", already_have_store: "Already has a store", timing: "Timing", trust: "Trust", existing_vendor: "Has a vendor", diy: "Prefers DIY" };
const ACTIVITY_ICON = { sentiment: "message", objection: "alert", stage_change: "target", opportunity: "target", next_action: "zap", meeting: "calendar", bant: "user" };

function FilterChips({ value, onChange }) {
  const { t } = useLang();
  const counts = {};
  // coerce object-shaped status (legacy/import edge) so counts + chips never mis-key
  DATA.CONTACTS.forEach((c) => { const s = crmOptKey(c.status); counts[s] = (counts[s] || 0) + 1; });
  const chips = [["all", t("allContacts"), DATA.CONTACTS.length], ...STATUS_ORDER.map((s) => [s, t(STATUS_META[s].key), counts[s] || 0])];
  return (
    <div className="chipscroll" style={{ gap: 8 }}>
      {chips.map(([k, label, n]) => (
        <button key={k} onClick={() => onChange(k)}
          style={{ flexShrink: 0, whiteSpace: "nowrap", height: 34, padding: "0 14px", borderRadius: 999, fontSize: 13, fontWeight: 600,
            border: "1px solid " + (value === k ? "var(--color-secondary)" : "var(--border-2)"),
            background: value === k ? "var(--color-secondary)" : "#fff",
            color: value === k ? "#fff" : "var(--fg-2)" }}>
          {label} <span style={{ opacity: 0.6, marginInlineStart: 4 }}>{n}</span>
        </button>
      ))}
    </div>
  );
}

function ContactRow({ c, onOpen, selecting, selected, onToggleSel }) {
  const camp = DATA.CAMPAIGNS.find((x) => x.id === c.campaign);
  const pm = priorityMeta(c.priority);
  return (
    <tr onClick={() => selecting ? onToggleSel(c.id) : onOpen(c)}>
      {selecting && <td style={{ width: 40 }} onClick={(e) => { e.stopPropagation(); onToggleSel(c.id); }}>
        <span style={{ width: 18, height: 18, borderRadius: 5, display: "inline-flex", alignItems: "center", justifyContent: "center", border: "1.5px solid " + (selected ? "var(--color-secondary)" : "var(--border-2)"), background: selected ? "var(--color-secondary)" : "#fff", color: "#fff", cursor: "pointer" }}>{selected && <Icon name="check" size={12} />}</span>
      </td>}
      <td>
        <div className="row" style={{ gap: 12 }}>
          <Avatar name={c.person} size="sm" />
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 14 }}>{c.name}</div>
            <div style={{ fontSize: 12, color: "var(--fg-4)" }}>{c.person} · {c.phone}</div>
            {(c.website || c.gmaps || c.googleMapsUrl) && <div className="row" style={{ gap: 8, marginTop: 2 }}>
              {c.website && <span className="row" style={{ gap: 3, fontSize: 11, color: "var(--color-secondary)" }}><Icon name="globe" size={11} />{String(c.website).replace(/^https?:\/\//, "").split("/")[0]}</span>}
              {(c.gmaps || c.googleMapsUrl) && <span className="row" style={{ gap: 3, fontSize: 11, color: "var(--fg-4)" }}><Icon name="mapPin" size={11} />Maps</span>}
            </div>}
          </div>
        </div>
      </td>
      <td><StatusPill status={crmOptKey(c.status)} /></td>
      <td>{c.website || c.analysis ? <AnalysisChip status={c.analysis || "not_analyzed"} /> : <span className="muted" style={{ fontSize: 12 }}>—</span>}</td>
      <td>
        <span className="row" style={{ gap: 6, fontWeight: 600 }}>
          <span className="sdot" style={{ background: pm.c }} />{pm.label}
        </span>
      </td>
      <td><div className="row" style={{ gap: 8 }}><Avatar name={agentNameOf(c)} size="sm" /><span style={{ fontSize: 13 }}>{agentNameOf(c)}</span></div></td>
      <td style={{ maxWidth: 200 }}>
        <div style={{ fontSize: 13, fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{c.next}</div>
        <div style={{ fontSize: 11, color: c.nextAt === "Now" || c.nextAt === "Overdue" ? "var(--color-warning)" : "var(--fg-4)", fontWeight: c.nextAt === "Now" || c.nextAt === "Overdue" ? 700 : 400 }}>{c.nextAt}</div>
      </td>
      <td style={{ color: "var(--fg-4)", fontSize: 12 }}>{c.lastReply}</td>
    </tr>
  );
}

// Row height used for virtualization math (keep in sync with .table cell padding).
const CONTACT_ROW_H = 57;
const VIRTUALIZE_OVER = 80; // only window large lists; small lists render in full
function ContactsList({ filter, onOpen, selecting, selectedSet, onToggleSel, onToggleAll }) {
  const { t } = useLang();
  const [q, setQ] = useState("");
  const [scrollTop, setScrollTop] = useState(0);
  const scRef = React.useRef(null);
  const [vh, setVh] = useState(620);
  React.useEffect(() => { if (scRef.current) setVh(scRef.current.clientHeight || 620); }, []);

  const term = q.trim().toLowerCase();
  const rows = DATA.CONTACTS.filter((c) =>
    (filter === "all" || crmOptKey(c.status) === filter) &&
    (!term || [c.name, c.person, c.phone, c.city, c.platform].some((v) => String(v || "").toLowerCase().includes(term))));
  const total = rows.length;
  const virtual = total > VIRTUALIZE_OVER;
  const overscan = 8;
  const start = virtual ? Math.max(0, Math.floor(scrollTop / CONTACT_ROW_H) - overscan) : 0;
  const windowCount = virtual ? Math.ceil(vh / CONTACT_ROW_H) + overscan * 2 : total;
  const end = virtual ? Math.min(total, start + windowCount) : total;
  const slice = rows.slice(start, end);
  const padTop = start * CONTACT_ROW_H;
  const padBot = Math.max(0, (total - end) * CONTACT_ROW_H);
  // selection-mode: select-all reflects the currently visible (filtered/searched) rows
  const allOn = selecting && rows.length > 0 && rows.every((c) => selectedSet && selectedSet.has(c.id));
  const colCount = selecting ? 8 : 7;

  return (
    <Card flush>
      <div className="between" style={{ padding: "12px 16px", borderBottom: "1px solid var(--border-1)" }}>
        <div className="search" style={{ width: 320, height: 38 }}>
          <Icon name="search" size={16} />
          <input placeholder="Search leads by name, phone, city…" value={q} onChange={(e) => setQ(e.target.value)} />
        </div>
        <span className="subtle" style={{ fontSize: 12 }}>{total.toLocaleString()} lead{total === 1 ? "" : "s"}{virtual ? " · virtualized" : ""}</span>
      </div>
      <div ref={scRef} onScroll={(e) => setScrollTop(e.currentTarget.scrollTop)} style={{ overflowY: "auto", overflowX: "auto", maxHeight: "62vh" }}>
        <table className="table">
          <thead><tr>
            {selecting && <th style={{ width: 40 }} onClick={() => onToggleAll(allOn ? [] : rows.map((c) => c.id))}>
              <span style={{ width: 18, height: 18, borderRadius: 5, display: "inline-flex", alignItems: "center", justifyContent: "center", border: "1.5px solid " + (allOn ? "var(--color-secondary)" : "var(--border-2)"), background: allOn ? "var(--color-secondary)" : "#fff", color: "#fff", cursor: "pointer" }}>{allOn && <Icon name="check" size={12} />}</span>
            </th>}
            <th>{t("table_contact")}</th><th>{t("table_status")}</th><th>Analysis</th><th>{t("table_priority")}</th>
            <th>{t("table_agent")}</th><th>{t("table_next")}</th><th>{t("table_lastReply")}</th>
          </tr></thead>
          <tbody>
            {padTop > 0 && <tr aria-hidden style={{ height: padTop }}><td colSpan={colCount} style={{ padding: 0, border: "none" }} /></tr>}
            {slice.map((c) => <ContactRow key={c.id} c={c} onOpen={onOpen} selecting={selecting} selected={selectedSet && selectedSet.has(c.id)} onToggleSel={onToggleSel} />)}
            {padBot > 0 && <tr aria-hidden style={{ height: padBot }}><td colSpan={colCount} style={{ padding: 0, border: "none" }} /></tr>}
            {total === 0 && <tr><td colSpan={colCount} style={{ textAlign: "center", padding: 32, color: "var(--fg-4)" }}>No leads match “{q}”.</td></tr>}
          </tbody>
        </table>
      </div>
    </Card>
  );
}

function BoardCard({ c, onOpen }) {
  const pm = priorityMeta(c.priority);
  return (
    <button className="card card--hover" onClick={() => onOpen(c)} style={{ padding: 14, textAlign: "start", display: "block", width: "100%", marginBottom: 10, cursor: "pointer" }}>
      <div className="between" style={{ marginBottom: 8 }}>
        <div className="row" style={{ gap: 8 }}><Avatar name={c.person} size="sm" /><span style={{ fontWeight: 700, fontSize: 13 }}>{c.name}</span></div>
        <OppBadge band={c.value} />
      </div>
      <div style={{ fontSize: 12, color: "var(--fg-3)", marginBottom: 10, lineHeight: 1.4, display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden" }}>{c.next}</div>
      <div className="between">
        <span className="row" style={{ gap: 5, fontSize: 11, fontWeight: 600, color: pm.c }}><span className="sdot" style={{ background: pm.c }} />{pm.label}</span>
        <span style={{ fontSize: 11, color: "var(--fg-4)" }}>{c.lastReply}</span>
      </div>
    </button>
  );
}

function ContactsBoard({ onOpen }) {
  const { t } = useLang();
  const cols = ["new", "contacted", "replied", "interested", "proposal", "won"];
  return (
    <div style={{ display: "flex", gap: 16, overflowX: "auto", paddingBottom: 8 }}>
      {cols.map((s) => {
        const items = DATA.CONTACTS.filter((c) => crmOptKey(c.status) === s);
        return (
          <div key={s} style={{ minWidth: 248, width: 248, flexShrink: 0 }}>
            <div className="between" style={{ marginBottom: 10, padding: "0 2px" }}>
              <span className="row" style={{ gap: 8 }}><span className="sdot" style={{ background: STATUS_META[s].color }} /><b style={{ fontSize: 13 }}>{t(STATUS_META[s].key)}</b></span>
              <span style={{ fontSize: 12, color: "var(--fg-4)", fontWeight: 600 }}>{items.length}</span>
            </div>
            {items.map((c) => <BoardCard key={c.id} c={c} onOpen={onOpen} />)}
            {items.length === 0 && <div style={{ border: "1.5px dashed var(--border-2)", borderRadius: 12, padding: 20, textAlign: "center", fontSize: 12, color: "var(--fg-disabled)" }}>Empty</div>}
          </div>
        );
      })}
    </div>
  );
}

function ContactsScreen() {
  const { t } = useLang();
  const { openContact, tweaks, setTweaks, startImport, startRetarget } = useApp();
  const data = useStore(); // re-render this subtree when CONTACTS change (import, status updates)
  const [filter, setFilter] = useState("all");
  const [overlay, setOverlay] = useState(null); // "add" | "discover"
  const [dupInfo, setDupInfo] = useState(null); // { groupCount, duplicateCount }
  const [confirm, setConfirm] = useState(null); // { kind: "dedupe" | "all" }
  const [confirmErr, setConfirmErr] = useState("");
  const [busy, setBusy] = useState(false);
  const [toast, setToast] = useState("");
  // multi-select mode (Select button → row checkboxes → bulk actions). Wired to the
  // REAL backend: bulk-analyze enqueues website/Maps jobs for the chosen subset, and
  // delete removes the chosen leads (no fake ticker / array splice like the prototype).
  const [selecting, setSelecting] = useState(false);
  const [sel, setSel] = useState(() => new Set());
  const view = tweaks.crmView || "list";
  const total = data.CONTACTS.length;
  const flash = (m) => { setToast(m); setTimeout(() => setToast(""), 2600); };

  const toggleSel = (id) => setSel((s) => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });
  const setAllSel = (ids) => setSel(new Set(ids));
  const exitSelect = () => { setSelecting(false); setSel(new Set()); };
  const bulkAnalyzeSel = async (kind) => {
    const ids = [...sel]; if (!ids.length || busy) return;
    setBusy(true);
    try {
      const r = await Actions.bulkAnalyze({ kind, contactIds: ids });
      const n = kind === "website" ? (r.website || 0) : (r.maps || 0);
      const noun = kind === "website" ? "website" : "Maps";
      flash(`Queued ${n} ${noun} analysis job${n === 1 ? "" : "s"}${r.skipped ? ` · ${r.skipped} had no ${kind === "website" ? "website" : "Maps URL"}` : ""}`);
    } catch (e) { flash(e.message || "Could not start analysis"); }
    finally { setBusy(false); exitSelect(); }
  };

  // live duplicate count from the backend (refreshes when the list changes)
  React.useEffect(() => {
    let alive = true;
    if (total === 0) { setDupInfo(null); return; }
    API.contacts.duplicates().then((r) => { if (alive) setDupInfo(r); }).catch(() => {});
    return () => { alive = false; };
  }, [total]);

  const dupCount = dupInfo?.duplicateCount || 0;

  const doConfirm = async () => {
    setBusy(true); setConfirmErr("");
    try {
      if (confirm.kind === "dedupe") { const r = await Actions.cleanDuplicates(); flash(`${r.removed} duplicate${r.removed === 1 ? "" : "s"} merged`); setDupInfo({ groupCount: 0, duplicateCount: 0 }); }
      else if (confirm.kind === "selected") {
        const ids = confirm.ids || []; let n = 0;
        for (const id of ids) { try { await Actions.deleteLead(id); n++; } catch {} }
        flash(`${n} contact${n === 1 ? "" : "s"} deleted`); exitSelect();
      }
      else { const r = await Actions.deleteAllContacts("DELETE CONTACTS"); if (!r.ok) { setConfirmErr(r.error || "Could not delete contacts — please try again."); return; } flash(`${r.deleted} contact${r.deleted === 1 ? "" : "s"} deleted`); }
      setConfirm(null);
    } catch (e) { setConfirmErr(e.message || "Something went wrong — please try again."); }
    finally { setBusy(false); }
  };

  return (
    <div className="content__inner content__inner--wide fade-up" style={{ maxWidth: 1320 }}>
      {/* Row 1 — title + count (left) / actions (right). In select mode the actions
          swap for a bulk action bar, mirroring the design. */}
      <div className="between" style={{ marginBottom: 16, gap: 12, flexWrap: "wrap", rowGap: 10 }}>
        <div className="row" style={{ gap: 10, minWidth: 0 }}>
          <h5 style={{ whiteSpace: "nowrap" }}>Contacts</h5>
          <span className="subtle" style={{ fontSize: 13 }}>{selecting ? `${sel.size} selected` : `${total} total`}</span>
        </div>
        <div className="row" style={{ gap: 10, flexWrap: "wrap" }}>
          {selecting ? (
            <>
              <button className="btn btn--ghost btn--sm" disabled={sel.size === 0 || busy} onClick={() => bulkAnalyzeSel("website")}><Icon name="globe" size={15} />Analyze Website</button>
              <button className="btn btn--ghost btn--sm" disabled={sel.size === 0 || busy} onClick={() => bulkAnalyzeSel("maps")}><Icon name="mapPin" size={15} />Analyze Maps</button>
              <button className="btn btn--ghost btn--sm" style={{ color: sel.size > 0 ? "var(--color-danger)" : undefined }} disabled={sel.size === 0 || busy} onClick={() => setConfirm({ kind: "selected", ids: [...sel] })}><Icon name="trash" size={15} />Delete</button>
              <button className="btn btn--subtle btn--sm" onClick={exitSelect}>Done</button>
            </>
          ) : (
            <>
              <button className="btn btn--ghost btn--sm" onClick={() => setOverlay("discover")} title="Demo feature — generates sample leads"><Icon name="search" size={16} />Discover<Badge tone="orange" style={{ marginInlineStart: 6 }}>Demo</Badge></button>
              <button className="btn btn--ghost btn--sm" onClick={startImport}><Icon name="upload" size={16} />Import</button>
              <button className="btn btn--ghost btn--sm" onClick={startRetarget}><Icon name="refresh" size={16} />Retarget</button>
              {view === "list" && total > 0 && <button className="btn btn--ghost btn--sm" onClick={() => setSelecting(true)}><Icon name="checkcircle" size={15} />Select</button>}
              <button className="btn btn--primary btn--sm" onClick={() => setOverlay("add")}><Icon name="plus" size={16} />Add lead</button>
              <Seg value={view} onChange={(v) => setTweaks({ crmView: v })}
                options={[{ value: "list", icon: "list", label: t("list") }, { value: "board", icon: "columns", label: t("board") }]} />
              <MoreContactsMenu hasContacts={total > 0} dupCount={dupCount} onDedupe={() => setConfirm({ kind: "dedupe" })} onDeleteAll={() => setConfirm({ kind: "all" })} onBulkAnalyze={(kind) => Actions.bulkAnalyze({ kind: kind || "both" })} />
            </>
          )}
        </div>
      </div>

      {/* duplicate notice banner (hidden while selecting) */}
      {!selecting && dupCount > 0 && (
        <div className="between" style={{ gap: 12, marginBottom: 16, padding: "10px 14px", background: "var(--color-orange-soft)", borderRadius: "var(--radius-md)" }}>
          <span className="row" style={{ gap: 8, fontSize: 13, color: "var(--fg-2)" }}><Icon name="copy" size={16} style={{ color: "var(--color-orange)" }} /><b>{dupCount} duplicate{dupCount === 1 ? "" : "s"} found</b> — matched by phone, email, website, Maps or company.</span>
          <button className="btn btn--subtle btn--sm" onClick={() => setConfirm({ kind: "dedupe" })} style={{ flexShrink: 0 }}><Icon name="copy" size={14} />Clean duplicates</button>
        </div>
      )}

      {/* Row 2 — status filter chips */}
      <div style={{ marginBottom: 20 }}><FilterChips value={filter} onChange={setFilter} /></div>

      {total === 0
        ? <Card><EmptyState icon="users" title="No leads yet" body="Import an Excel/CSV list, discover stores on Shopify, Salla or Zid — or add a lead manually — then run the Dynamic Workflow." action={<div className="row" style={{ gap: 10, justifyContent: "center" }}><Button variant="primary" icon="upload" onClick={startImport}>Import contacts</Button><Button variant="ghost" icon="search" onClick={() => setOverlay("discover")}>Discover leads</Button></div>} /></Card>
        : (view === "list"
            ? <ContactsList filter={filter} onOpen={openContact} selecting={selecting} selectedSet={sel} onToggleSel={toggleSel} onToggleAll={setAllSel} />
            : <ContactsBoard onOpen={openContact} />)}

      {toast && <div className="fade-up" style={{ position: "fixed", bottom: 24, insetInlineStart: "50%", transform: "translateX(-50%)", background: "var(--color-secondary)", color: "#fff", padding: "12px 20px", borderRadius: "var(--radius-md)", boxShadow: "var(--shadow-lg)", fontSize: 13.5, fontWeight: 600, zIndex: 60, display: "flex", alignItems: "center", gap: 8 }}><Icon name="checkcircle" size={16} />{toast}</div>}
      {confirm && <DeleteContactsModal kind={confirm.kind} count={confirm.kind === "dedupe" ? dupCount : confirm.kind === "selected" ? (confirm.ids || []).length : total} busy={busy} error={confirmErr} onClose={() => !busy && (setConfirm(null), setConfirmErr(""))} onConfirm={doConfirm} />}
      {overlay === "add" && <AddLeadModal onClose={() => setOverlay(null)} onCreated={openContact} />}
      {overlay === "discover" && <DiscoverLeadsModal onClose={() => setOverlay(null)} />}
    </div>
  );
}

/* ---- Contacts bulk-ops menu + delete/dedupe modal (Phases 3-4, 10) ----- */
function MoreContactsMenu({ hasContacts, dupCount, onDedupe, onDeleteAll, onBulkAnalyze }) {
  const [open, setOpen] = useState(false);
  const [busy, setBusy] = useState(false);
  const [done, setDone] = useState(null);
  const analyze = async (kind) => { setBusy(kind); setDone(null); try { setDone(await onBulkAnalyze(kind)); } catch { setDone({ error: true }); } finally { setBusy(false); } };
  return (
    <div style={{ position: "relative" }}>
      <button className="iconbtn" style={{ width: 32, height: 32 }} title="More" onClick={() => setOpen((o) => !o)}><Icon name="moreV" size={18} /></button>
      {open && <>
        <div style={{ position: "fixed", inset: 0, zIndex: 51 }} onClick={() => setOpen(false)} />
        <div style={{ position: "absolute", top: 38, insetInlineEnd: 0, zIndex: 52, width: 248, background: "#fff", border: "1px solid var(--border-1)", borderRadius: "var(--radius-md)", boxShadow: "var(--shadow-lg)", padding: 6 }}>
          {/* bulk analysis — per channel (Website / Maps) or both, all wired to the real
              bulk-analyze endpoint which enqueues the async jobs for contacts that have a URL. */}
          <button className="navitem" style={{ marginBottom: 0 }} disabled={!hasContacts || !!busy} onClick={() => analyze("website")}><Icon name="globe" size={16} />{busy === "website" ? "Queuing…" : "Analyze Website"}</button>
          <button className="navitem" style={{ marginBottom: 0 }} disabled={!hasContacts || !!busy} onClick={() => analyze("maps")}><Icon name="mapPin" size={16} />{busy === "maps" ? "Queuing…" : "Analyze Google Maps"}</button>
          <button className="navitem" style={{ marginBottom: 0 }} disabled={!hasContacts || !!busy} onClick={() => analyze("both")}><Icon name="sparkles" size={16} />{busy === "both" ? "Queuing…" : "Analyze all (Website + Maps)"}</button>
          {done && !done.error && <div className="muted" style={{ fontSize: 11.5, padding: "2px 10px 6px" }}>{done.queued} job{done.queued === 1 ? "" : "s"} queued · {done.website} website · {done.maps} maps</div>}
          <div style={{ height: 1, background: "var(--border-1)", margin: "6px 4px" }} />
          <button className="navitem" style={{ marginBottom: 0 }} disabled={dupCount === 0} onClick={() => { if (dupCount === 0) return; onDedupe(); setOpen(false); }}>
            <Icon name="copy" size={16} />Clean duplicates
            {dupCount > 0 && <span style={{ marginInlineStart: "auto", background: "var(--color-orange)", color: "#fff", borderRadius: 999, padding: "0 7px", fontSize: 11, fontWeight: 700 }}>{dupCount}</span>}
          </button>
          <div style={{ height: 1, background: "var(--border-1)", margin: "6px 4px" }} />
          <button className="navitem" style={{ marginBottom: 0, color: "var(--color-danger)", opacity: hasContacts ? 1 : 0.4 }} disabled={!hasContacts} onClick={() => { if (!hasContacts) return; onDeleteAll(); setOpen(false); }}>
            <Icon name="trash" size={16} />Delete all contacts
          </button>
        </div>
      </>}
    </div>
  );
}

function DeleteContactsModal({ kind, count, busy, error, onClose, onConfirm }) {
  const [typed, setTyped] = useState("");
  const needType = kind === "all";
  const ok = !needType || typed.trim().toUpperCase() === "DELETE CONTACTS";
  const copy = kind === "dedupe"
    ? { title: `Clean ${count} duplicate${count === 1 ? "" : "s"}?`, body: "Duplicates are matched by phone, email, website, Google Maps URL or company. The best record is kept and conversations, BANT, intelligence, notes and follow-ups are merged into it — only the extra copies are removed.", btn: "Clean duplicates", danger: false }
    : kind === "selected"
      ? { title: `Delete ${count} selected contact${count === 1 ? "" : "s"}?`, body: "The selected contacts, with their conversation history and scheduled follow-ups, will be permanently removed. Your other contacts, agents, campaigns and settings are untouched.", btn: `Delete ${count} contact${count === 1 ? "" : "s"}`, danger: true }
      : { title: `Delete all ${count} contacts?`, body: "Every contact, with its conversation history and scheduled follow-ups, will be permanently removed. Your agents, campaigns, WhatsApp lines, settings, API keys and service packages are kept.", btn: "Delete all contacts", danger: true };
  return (
    <Modal onClose={onClose} style={{ width: 460 }}>
      <div style={{ padding: 24 }}>
        <span className="opp" style={{ width: 48, height: 48, borderRadius: 14, background: copy.danger ? "var(--color-danger-soft)" : "var(--color-orange-soft)", color: copy.danger ? "var(--color-danger)" : "var(--color-orange)", marginBottom: 16 }}><Icon name={kind === "dedupe" ? "copy" : "trash"} size={22} /></span>
        <div style={{ fontWeight: 800, fontSize: 17, marginBottom: 6 }}>{copy.title}</div>
        <p className="muted" style={{ fontSize: 13.5, lineHeight: 1.55, marginBottom: needType ? 14 : 18 }}>{copy.body}</p>
        {needType && (
          <div style={{ marginBottom: 18 }}>
            <div className="field__label" style={{ marginBottom: 6 }}>Type <b style={{ color: "var(--color-danger)" }}>DELETE CONTACTS</b> to confirm</div>
            <input className="input" autoFocus value={typed} onChange={(e) => setTyped(e.target.value)} placeholder="DELETE CONTACTS" style={{ fontFamily: "monospace", letterSpacing: "0.04em" }} />
          </div>
        )}
        {error && <div className="row" style={{ gap: 8, marginBottom: 12, background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 10, padding: "10px 12px", fontSize: 13 }}><Icon name="alert" size={15} />{error}</div>}
        <div className="row" style={{ gap: 10, justifyContent: "flex-end" }}>
          <Button variant="ghost" onClick={onClose} disabled={busy}>Cancel</Button>
          <button className="btn" disabled={busy || !ok} onClick={onConfirm} style={{ background: copy.danger ? "var(--color-danger)" : "var(--color-secondary)", color: "#fff", opacity: ok && !busy ? 1 : 0.5, cursor: ok && !busy ? "pointer" : "not-allowed" }}>
            {busy ? <><span className="spin" style={{ width: 15, height: 15, borderTopColor: "#fff", borderColor: "rgba(255,255,255,.35)" }} />Working…</> : <><Icon name={kind === "dedupe" ? "copy" : "trash"} size={16} />{error ? "Try again" : copy.btn}</>}
          </button>
        </div>
      </div>
    </Modal>
  );
}

/* ---- Save-state helpers (loading / saved / error feedback) ------------- */
// Tracks the lifecycle of a save call so controls can show saving → saved →
// error inline. `run(fn)` runs the async work and transitions the state.
function useSaver() {
  const [state, setState] = useState({ status: "idle", error: null }); // idle|saving|saved|error
  const mounted = React.useRef(true);
  React.useEffect(() => () => { mounted.current = false; }, []);
  const run = async (fn) => {
    setState({ status: "saving", error: null });
    try {
      const r = await fn();
      if (mounted.current) {
        setState({ status: "saved", error: null });
        setTimeout(() => { if (mounted.current) setState((s) => (s.status === "saved" ? { status: "idle", error: null } : s)); }, 1600);
      }
      return r;
    } catch (e) {
      if (mounted.current) setState({ status: "error", error: e.message || "Something went wrong" });
      throw e;
    }
  };
  return [state, run];
}

function SaveBadge({ state }) {
  if (state.status === "saving") return <span className="row" style={{ gap: 6, fontSize: 12, color: "var(--fg-4)", fontWeight: 600 }}><span className="skel" style={{ width: 14, height: 14, borderRadius: 999 }} />Saving…</span>;
  if (state.status === "saved") return <span className="row" style={{ gap: 5, fontSize: 12, color: "#15803D", fontWeight: 700 }}><Icon name="checkcircle" size={14} />Saved</span>;
  if (state.status === "error") return <span className="row" style={{ gap: 5, fontSize: 12, color: "var(--color-danger)", fontWeight: 700 }}><Icon name="alert" size={14} />Error</span>;
  return null;
}

function ErrorNote({ msg, style }) {
  return <div style={{ background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 8, padding: "8px 10px", fontSize: 12.5, lineHeight: 1.5, ...style }}>{msg}</div>;
}

/* ---- CRM stage / status control (manual pipeline control) -------------- */
function LeadCrmCard({ contact: c }) {
  const { t } = useLang();
  const data = useStore();
  const stages = data.CRM_STAGES || [];
  const statuses = (data.SETTINGS && data.SETTINGS.statuses) || STATUS_ORDER;
  const [save, runSave] = useSaver();
  const statusLabel = (s) => { const k = crmOptKey(s); return STATUS_META[k] ? t(STATUS_META[k].key) : crmOptText(s); };
  const currentStage = crmOptKey(c.stage);
  const currentStatus = crmOptKey(c.status);
  const update = (patch) => { runSave(() => Actions.updateLead(c.id, patch)).catch(() => {}); };

  return (
    <Card title="CRM status & stage" action={<SaveBadge state={save} />}>
      <div className="between" style={{ marginBottom: 14 }}>
        <span className="muted" style={{ fontSize: 13 }}>Current stage</span>
        {currentStage ? <Badge tone="dark">{currentStage}</Badge> : <Badge tone="neutral">Not set</Badge>}
      </div>
      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <Field label="Pipeline stage">
          <select className="select" style={{ height: 40 }} value={currentStage} disabled={save.status === "saving"} onChange={(e) => update({ stage: e.target.value })}>
            <option value="">— Not set —</option>
            {stages.map((s) => { const k = crmOptKey(s); return <option key={k} value={k}>{crmOptText(s)}</option>; })}
          </select>
        </Field>
        <Field label="CRM status">
          <select className="select" style={{ height: 40 }} value={currentStatus} disabled={save.status === "saving"} onChange={(e) => update({ status: e.target.value })}>
            {statuses.map((s) => { const k = crmOptKey(s); return <option key={k} value={k}>{statusLabel(s)}</option>; })}
          </select>
        </Field>
      </div>
      {save.status === "error" && <ErrorNote msg={save.error} style={{ marginTop: 4 }} />}
    </Card>
  );
}

/* ---- Manual follow-up scheduling --------------------------------------- */
const FU_TYPES = ["Call", "WhatsApp", "Email", "Meeting", "Other"];
const FU_STATUSES = ["scheduled", "done", "cancelled"];
const FU_STATUS_TONE = { scheduled: "blue", done: "green", cancelled: "neutral" };
const blankFollowUp = () => ({ date: "", time: "", type: "Call", note: "", status: "scheduled" });

function LeadFollowUps({ contact: c }) {
  const data = useStore();
  const list = (data.FOLLOW_UPS || []).filter((f) => f.leadId === c.id);
  const [form, setForm] = useState(blankFollowUp);
  const [save, runSave] = useSaver();
  const [loading, setLoading] = useState(true);
  const set = (k, v) => setForm((s) => ({ ...s, [k]: v }));

  React.useEffect(() => {
    setLoading(true);
    Actions.loadFollowUps(c.id).catch(() => {}).finally(() => setLoading(false));
  }, [c.id]); // eslint-disable-line

  const canSubmit = Boolean(form.date || form.note.trim());
  const submit = async () => {
    if (!canSubmit || save.status === "saving") return;
    try {
      await runSave(() => Actions.createFollowUp({ leadId: c.id, date: form.date, time: form.time, type: form.type, note: form.note.trim(), status: form.status }));
      setForm(blankFollowUp());
    } catch (e) { /* error surfaced by SaveBadge + ErrorNote */ }
  };

  return (
    <Card title="Follow-ups" action={<SaveBadge state={save} />}>
      {/* existing follow-ups / empty + loading states */}
      {loading ? (
        <div className="col" style={{ gap: 8 }}>
          <div className="skel" style={{ height: 44, borderRadius: 10 }} />
          <div className="skel" style={{ height: 44, borderRadius: 10 }} />
        </div>
      ) : list.length === 0 ? (
        <div style={{ border: "1.5px dashed var(--border-2)", borderRadius: 12, padding: "20px 16px", textAlign: "center" }}>
          <Icon name="calendar" size={22} style={{ color: "var(--fg-disabled)" }} />
          <div style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-2)", marginTop: 6 }}>No follow-ups scheduled</div>
          <div style={{ fontSize: 12, color: "var(--fg-4)", marginTop: 2 }}>Schedule one below to stay on top of this lead.</div>
        </div>
      ) : (
        <div className="col" style={{ gap: 8 }}>
          {list.map((f) => (
            <div key={f.id} className="between" style={{ gap: 10, border: "1px solid var(--border-1)", borderRadius: 10, padding: "10px 12px" }}>
              <div className="row" style={{ gap: 10, minWidth: 0 }}>
                <span className="opp" style={{ width: 28, height: 28, borderRadius: 8, background: "var(--bg-2)", color: "var(--color-secondary)", flexShrink: 0 }}><Icon name="clock" size={14} /></span>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-1)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{f.note || f.action || "Follow up"}</div>
                  <div style={{ fontSize: 11.5, color: "var(--fg-4)" }}>{[f.type, f.date || f.when, f.time].filter(Boolean).join(" · ")}</div>
                </div>
              </div>
              <Badge tone={FU_STATUS_TONE[f.status] || "neutral"}>{f.status || "scheduled"}</Badge>
            </div>
          ))}
        </div>
      )}

      {/* scheduler form */}
      <div className="divider" style={{ margin: "14px 0" }} />
      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <Field label="Date"><input className="input" style={{ height: 40 }} type="date" value={form.date} onChange={(e) => set("date", e.target.value)} /></Field>
        <Field label="Time"><input className="input" style={{ height: 40 }} type="time" value={form.time} onChange={(e) => set("time", e.target.value)} /></Field>
        <Field label="Type"><select className="select" style={{ height: 40 }} value={form.type} onChange={(e) => set("type", e.target.value)}>{FU_TYPES.map((x) => <option key={x} value={x}>{x}</option>)}</select></Field>
        <Field label="Status"><select className="select" style={{ height: 40 }} value={form.status} onChange={(e) => set("status", e.target.value)}>{FU_STATUSES.map((x) => <option key={x} value={x}>{x}</option>)}</select></Field>
      </div>
      <Field label="Note">
        <input className="input" dir="auto" placeholder="What's the follow-up about?" value={form.note} onChange={(e) => set("note", e.target.value)} onKeyDown={(e) => e.key === "Enter" && submit()} />
      </Field>
      {save.status === "error" && <ErrorNote msg={save.error} style={{ marginBottom: 10 }} />}
      <div className="row" style={{ justifyContent: "flex-end" }}>
        <Button variant="primary" size="sm" icon="calendar" disabled={!canSubmit || save.status === "saving"} onClick={submit}>{save.status === "saving" ? "Scheduling…" : "Schedule follow-up"}</Button>
      </div>
    </Card>
  );
}

/* ---- Google Meet scheduler card (Phase 5) ------------------------------ */
const MEETING_STATUS_META = {
  proposed: { label: "Proposed", tone: "neutral", c: "#9CA3AF" },
  scheduled: { label: "Scheduled", tone: "blue", c: "#2563EB" },
  confirmed: { label: "Confirmed", tone: "green", c: "#22C55E" },
  completed: { label: "Completed", tone: "green", c: "#15803D" },
  cancelled: { label: "Cancelled", tone: "neutral", c: "#9CA3AF" },
  no_show: { label: "No-show", tone: "orange", c: "#EA580C" },
};
function MeetingCard({ contact: c }) {
  const m = c.meeting || null;
  const [open, setOpen] = useState(!m);
  const [f, setF] = useState({ date: m?.date || "", time: m?.time || "", link: m?.link || "", status: m?.status || "scheduled", note: "" });
  const [busy, setBusy] = useState(false);
  const set = (k, v) => setF((s) => ({ ...s, [k]: v }));
  const save = async () => { setBusy(true); try { await Actions.setMeeting(c.id, f); setOpen(false); } catch (e) { /* surfaced by store */ } finally { setBusy(false); } };
  const meta = m ? (MEETING_STATUS_META[m.status] || MEETING_STATUS_META.proposed) : null;
  return (
    <Card title="Google Meet">
      {m && !open ? (
        <div className="col" style={{ gap: 10 }}>
          <div className="between"><Badge tone={meta.tone} dot={meta.c}>{meta.label}</Badge><Button variant="ghost" size="sm" icon="edit" onClick={() => setOpen(true)}>Update</Button></div>
          {(m.date || m.time) && <KV k="When" v={[m.date, m.time].filter(Boolean).join(" · ")} />}
          {m.link && <KV k="Meeting link" v={<a href={m.link} target="_blank" rel="noreferrer" style={{ color: "var(--color-secondary)" }}>Open Google Meet</a>} />}
          {m.note && <KV k="Note" v={m.note} />}
          {(m.history || []).length > 0 && <div className="muted" style={{ fontSize: 11.5 }}>{m.history.length} update{m.history.length > 1 ? "s" : ""} · last: {(m.history[m.history.length - 1] || {}).status}</div>}
        </div>
      ) : (
        <div className="col" style={{ gap: 10 }}>
          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 10 }}>
            <Field label="Date"><input className="input" value={f.date} onChange={(e) => set("date", e.target.value)} placeholder="e.g. Sunday, or YYYY-MM-DD" /></Field>
            <Field label="Time"><input className="input" value={f.time} onChange={(e) => set("time", e.target.value)} placeholder="10:00 AM" /></Field>
          </div>
          <Field label="Google Meet link" hint="Create the Meet and paste the link — never fabricated."><input className="input" dir="ltr" value={f.link} onChange={(e) => set("link", e.target.value)} placeholder="https://meet.google.com/…" /></Field>
          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 10 }}>
            <Field label="Status"><select className="select" value={f.status} onChange={(e) => set("status", e.target.value)}>{Object.keys(MEETING_STATUS_META).map((k) => <option key={k} value={k}>{MEETING_STATUS_META[k].label}</option>)}</select></Field>
            <Field label="Note (optional)"><input className="input" value={f.note} onChange={(e) => set("note", e.target.value)} placeholder="e.g. demo for the owner" /></Field>
          </div>
          <div className="row" style={{ gap: 8, justifyContent: "flex-end" }}>
            {m && <Button variant="ghost" size="sm" onClick={() => setOpen(false)}>Cancel</Button>}
            <Button variant="primary" size="sm" icon="calendar" disabled={busy} onClick={save}>{busy ? "Saving…" : m ? "Update meeting" : "Schedule Meet"}</Button>
          </div>
        </div>
      )}
    </Card>
  );
}

/* ---- Delete lead confirmation modal ------------------------------------ */
function DeleteLeadModal({ contact: c, onClose, onDeleted }) {
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);
  const confirm = async () => {
    setBusy(true); setErr(null);
    try { await Actions.deleteLead(c.id); onDeleted(); }
    catch (e) { setErr(e.message || "Couldn't delete this lead — please try again."); setBusy(false); }
  };
  return (
    <Modal onClose={busy ? () => {} : onClose} style={{ width: 440 }}>
      <div style={{ padding: 24 }}>
        <div className="row" style={{ gap: 12, marginBottom: 12 }}>
          <span className="opp" style={{ width: 44, height: 44, borderRadius: 12, background: "var(--color-danger-soft)", color: "var(--color-danger)", flexShrink: 0 }}><Icon name="trash" size={20} /></span>
          <div>
            <div style={{ fontWeight: 800, fontSize: 16 }}>Delete lead</div>
            <div style={{ fontSize: 12, color: "var(--fg-4)" }}>This can't be undone</div>
          </div>
        </div>
        <p style={{ fontSize: 13.5, color: "var(--fg-2)", lineHeight: 1.6, marginBottom: err ? 12 : 18 }}>
          Permanently delete <b>{c.name}</b>? Its workflow runs, follow-ups and notes will be removed too.
        </p>
        {err && <ErrorNote msg={err} style={{ marginBottom: 16 }} />}
        <div className="row" style={{ gap: 10, justifyContent: "flex-end" }}>
          <Button variant="ghost" onClick={onClose} disabled={busy}>Cancel</Button>
          <Button variant="dark" icon="trash" style={{ background: "var(--color-danger)", color: "#fff" }} disabled={busy} onClick={confirm}>{busy ? "Deleting…" : "Delete lead"}</Button>
        </div>
      </div>
    </Modal>
  );
}

/* ---- Lead Intelligence tabs (Phase 7) ---------------------------------- */
// Renders the unified Lead Intelligence (one read from /contacts/:id/intelligence)
// across Website / Google Maps / Products / Sales angles. Every action is wired
// to the real backend — analyze, re-analyze, copy brief, send to campaign, add
// to agent memory. No placeholders.
const ANALYSIS_STATUS = {
  not_analyzed: { label: "Not analyzed", tone: "neutral", c: "#9CA3AF" },
  analyzing: { label: "Analyzing…", tone: "blue", c: "#2563EB" },
  analyzed: { label: "Completed", tone: "green", c: "#22C55E" },
  completed: { label: "Completed", tone: "green", c: "#22C55E" },
  failed: { label: "Analysis failed", tone: "red", c: "#B91C1C" },
  queued: { label: "Queued", tone: "neutral", c: "#9CA3AF" },
};
// Format an ISO/clock time for "Last analyzed" — tolerant of either shape.
function fmtAnalyzedAt(t) {
  if (!t) return null;
  try { const d = new Date(t); if (!isNaN(d)) return d.toLocaleString(undefined, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }); } catch {}
  return String(t);
}
// Always-visible analysis status header (status pill + last-analyzed + the real
// URL + retry/re-analyze) — so intelligence status is never hidden. Real data only.
function AnalysisStatusHeader({ kind, status, url, analyzedAt, busy, onAnalyze, canAnalyze }) {
  const failed = status === "failed";
  const done = status === "analyzed" || status === "completed";
  const btnLabel = failed ? `Retry ${kind}` : done ? `Re-analyze ${kind}` : `Analyze ${kind}`;
  return (
    <div className="between" style={{ gap: 10, background: "var(--bg-2)", border: "1px solid var(--border-1)", borderRadius: 12, padding: "12px 14px", flexWrap: "wrap" }}>
      <div className="col" style={{ gap: 4, minWidth: 0 }}>
        <div className="row" style={{ gap: 8 }}>
          <span className="muted" style={{ fontSize: 12 }}>{kind === "website" ? "Website analysis" : "Google Maps analysis"}</span>
          <AnalysisChip status={status || "not_analyzed"} />
        </div>
        {url ? <a href={/^https?:/i.test(url) ? url : "https://" + url} target="_blank" rel="noreferrer" className="row" style={{ gap: 5, fontSize: 12, color: "var(--color-secondary)", minWidth: 0 }}><Icon name={kind === "website" ? "globe" : "mapPin"} size={12} /><span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{String(url).replace(/^https?:\/\//, "")}</span></a> : <span className="muted" style={{ fontSize: 12 }}>No {kind === "website" ? "website" : "Google Maps"} URL on file</span>}
        {analyzedAt && <span className="muted" style={{ fontSize: 11.5 }}>Last analyzed {fmtAnalyzedAt(analyzedAt)}</span>}
      </div>
      {canAnalyze && <Button variant={failed ? "dark" : "ghost"} size="sm" icon="refresh" disabled={busy} onClick={onAnalyze}>{busy ? "Working…" : btnLabel}</Button>}
    </div>
  );
}
function AnalysisChip({ status }) {
  if (!status) return null;
  const m = ANALYSIS_STATUS[status] || ANALYSIS_STATUS.not_analyzed;
  return <Badge tone={m.tone} dot={m.c}>{m.label}</Badge>;
}
function KV({ k, v, mono }) {
  return (
    <div className="between" style={{ gap: 12, padding: "8px 0", borderBottom: "1px solid var(--border-1)", alignItems: "flex-start" }}>
      <span className="muted" style={{ fontSize: 12.5, flexShrink: 0 }}>{k}</span>
      <span style={{ fontSize: 13, fontWeight: 600, textAlign: "end", fontFamily: mono ? "monospace" : "inherit", wordBreak: "break-word" }} dir="auto">{v}</span>
    </div>
  );
}
function TagRow({ items, tone = "neutral" }) {
  if (!items || !items.length) return <span className="muted" style={{ fontSize: 13 }}>—</span>;
  return <div className="row wrap" style={{ gap: 6 }}>{items.map((x, i) => <Badge key={i} tone={tone}>{x}</Badge>)}</div>;
}
function IntelEmpty({ icon, title, body, action, spin }) {
  return (
    <div style={{ textAlign: "center", padding: "40px 20px", color: "var(--fg-4)" }}>
      <span className="opp" style={{ width: 56, height: 56, borderRadius: 16, background: "var(--bg-2)", color: spin ? "var(--color-secondary)" : "var(--fg-disabled)", margin: "0 auto 14px" }}>
        {spin ? <span className="spin" style={{ width: 24, height: 24 }} /> : <Icon name={icon} size={26} />}
      </span>
      <div style={{ fontSize: 14, fontWeight: 700, color: "var(--fg-1)" }}>{title}</div>
      {body && <p style={{ fontSize: 13, maxWidth: 320, margin: "6px auto 16px", lineHeight: 1.5 }} dir="auto">{body}</p>}
      {action}
    </div>
  );
}
function RecoBanner({ icon, title, children }) {
  return (
    <div style={{ background: "var(--color-primary-tint-soft)", border: "1px solid var(--color-primary-tint)", borderRadius: 16, padding: 18 }}>
      <div className="row" style={{ gap: 8, marginBottom: 8 }}><Icon name={icon} size={18} style={{ color: "var(--color-secondary)" }} /><b style={{ color: "var(--color-secondary)", fontSize: 13 }}>{title}</b></div>
      {children}
    </div>
  );
}

function WebsiteTab({ c, intel, busy, onAnalyze, loading, job }) {
  const web = intel && intel.website;
  // Live status: an in-flight async job wins, then the contact flag, then the report.
  const jobStatus = job && ({ queued: "queued", running: "analyzing", completed: "analyzed", failed: "failed" }[job.status]);
  const status = busy ? "analyzing" : (jobStatus || c.analysis || (web && web.status === "analyzed" ? "analyzed" : (c.website ? "not_analyzed" : null)));
  const header = <AnalysisStatusHeader kind="website" status={status} url={web?.url || c.website} analyzedAt={web?.analyzedAt} busy={busy || status === "analyzing" || status === "queued"} onAnalyze={onAnalyze} canAnalyze={!!c.website} />;
  if (!c.website) return <IntelEmpty icon="globe" title="No website on file" body="Add a website to this lead (Edit lead) to enable Website Intelligence." />;
  if (status === "queued") return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty spin title="Queued for analysis…" body="This website is in the analysis queue — it will start shortly." /></div>;
  if (status === "analyzing") return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty spin title="Analyzing website…" body={`The Website Analysis agent is reading ${c.website.replace(/^https?:\/\//, "")} — platform, niche, weaknesses and sales angles.`} /></div>;
  if (loading && !intel) return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty spin title="Loading intelligence…" /></div>;
  if (status === "failed" || (web && web.status === "failed")) return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty icon="alert" title="Analysis failed" body={(web && web.error) || (job && job.error) || "We couldn't reach the website. Check the URL and try again."} action={<Button variant="dark" size="sm" icon="refresh" onClick={onAnalyze}>Retry analysis</Button>} /></div>;
  if (!web || web.status !== "analyzed") return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty icon="globe" title="Not analyzed yet" body="Run the Website Analysis agent to extract platform, niche, weaknesses and sales angles." action={<Button variant="primary" size="sm" icon="sparkles" onClick={onAnalyze}>Analyze website</Button>} /></div>;
  return (
    <div className="col" style={{ gap: 16 }}>
      {header}
      <Card title="Detected">
        <KV k="Platform" v={<Badge tone="blue">{crmOptText(web.platform)}</Badge>} />
        {web.niche && <KV k="Business niche" v={web.niche} />}
        {web.positioning && <KV k="Positioning" v={web.positioning} />}
        {web.categories && web.categories.length > 0 && <div style={{ paddingTop: 8 }}><div className="muted" style={{ fontSize: 12.5, marginBottom: 6 }}>Product categories</div><TagRow items={web.categories} tone="purple" /></div>}
        {!web.aiEnriched && <div className="muted" style={{ fontSize: 12, marginTop: 8 }}>Signals below are extracted directly from the page. Niche/products need a live AI key to enrich.</div>}
      </Card>
      <Card title="Store quality & trust">
        {web.design && <KV k="Design read" v={web.design} />}
        <div style={{ padding: "8px 0" }}><div className="muted" style={{ fontSize: 12.5, marginBottom: 6 }}>Trust signals</div><TagRow items={web.trust} tone="green" /></div>
        <div style={{ padding: "8px 0" }}><div className="muted" style={{ fontSize: 12.5, marginBottom: 6 }}>Payments</div><TagRow items={web.payments} tone="blue" /></div>
        <div style={{ padding: "8px 0" }}><div className="muted" style={{ fontSize: 12.5, marginBottom: 6 }}>SEO signals</div><TagRow items={web.seo} /></div>
        <div style={{ padding: "8px 0" }}><div className="muted" style={{ fontSize: 12.5, marginBottom: 6 }}>Tech stack</div><TagRow items={web.stack} /></div>
        <div style={{ paddingTop: 8 }}><div className="muted" style={{ fontSize: 12.5, marginBottom: 6 }}>Social</div><TagRow items={web.social} tone="purple" /></div>
      </Card>
      {web.weaknesses && web.weaknesses.length > 0 && <Card title="Main weaknesses">
        <div className="col" style={{ gap: 8 }}>{web.weaknesses.map((x, i) => <div key={i} className="row" style={{ gap: 8, fontSize: 13 }}><Icon name="alert" size={15} style={{ color: "var(--color-orange)", flexShrink: 0, marginTop: 1 }} /><span style={{ color: "var(--fg-2)" }} dir="auto">{x}</span></div>)}</div>
      </Card>}
      {web.opportunities && web.opportunities.length > 0 && <Card title="Opportunities">
        <div className="col" style={{ gap: 8 }}>{web.opportunities.map((x, i) => <div key={i} className="row" style={{ gap: 8, fontSize: 13 }}><Icon name="trendingup" size={15} style={{ color: "var(--color-secondary)", flexShrink: 0, marginTop: 1 }} /><span style={{ color: "var(--fg-2)" }} dir="auto">{x}</span></div>)}</div>
      </Card>}
      {(web.title || web.url) && <Card title="Source evidence">
        <div className="muted" style={{ fontSize: 12, marginBottom: 6 }}>Read directly from the live website{web.aiEnriched ? " and enriched by AI" : ""}.</div>
        {web.title && <KV k="Page title" v={web.title} />}
        <KV k="Source URL" v={<a href={/^https?:/i.test(web.url || c.website) ? (web.url || c.website) : "https://" + (web.url || c.website)} target="_blank" rel="noreferrer" style={{ color: "var(--color-secondary)" }}>{(web.url || c.website).replace(/^https?:\/\//, "")}</a>} />
      </Card>}
      <RecoBanner icon="sparkles" title="Recommended Maxab service">
        <Badge tone="dark">{web.service}</Badge>
        {web.talking && web.talking.length > 0 && <div style={{ marginTop: 12 }}><div className="muted" style={{ fontSize: 12.5, marginBottom: 6 }}>Sales talking points</div><div className="col" style={{ gap: 6 }}>{web.talking.map((x, i) => <div key={i} className="row" style={{ gap: 8, fontSize: 13 }}><Icon name="check" size={14} style={{ color: "var(--color-secondary)", flexShrink: 0, marginTop: 2 }} /><span dir="auto">{x}</span></div>)}</div></div>}
      </RecoBanner>
    </div>
  );
}

function MapsTab({ c, intel, busy, onAnalyze, loading }) {
  const url = c.gmaps || c.googleMapsUrl;
  const maps = intel && intel.maps;
  const status = busy ? "analyzing" : (!url ? null : (maps?.status === "analyzed" ? "analyzed" : (maps?.status === "failed" || maps?.status === "unavailable" ? "failed" : (maps ? "analyzed" : "not_analyzed"))));
  const header = <AnalysisStatusHeader kind="maps" status={status} url={url} analyzedAt={maps?.analyzedAt} busy={busy} onAnalyze={onAnalyze} canAnalyze={!!url} />;
  if (!url) return <IntelEmpty icon="mapPin" title="No Google Maps profile" body="No Google Maps URL on file. Add one (Edit lead) to pull business data." />;
  if (busy) return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty spin title="Reading Google Maps…" body="Pulling ratings, reviews and sentiment from the listing." /></div>;
  if (loading && !intel) return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty spin title="Loading intelligence…" /></div>;
  if (!maps) return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty icon="mapPin" title="Maps not analyzed" body="Pull ratings, reviews, hours and customer sentiment from the Google Maps listing." action={<Button variant="primary" size="sm" icon="sparkles" onClick={onAnalyze}>Analyze Google Maps</Button>} /></div>;
  if (maps.status === "unavailable") return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty icon="alert" title="Google Maps needs a Places API key" body={maps.error} action={<Button variant="ghost" size="sm" icon="refresh" onClick={onAnalyze}>Try again</Button>} /></div>;
  if (maps.status === "failed") return <div className="col" style={{ gap: 16 }}>{header}<IntelEmpty icon="alert" title="Couldn't read the listing" body={maps.error} action={<Button variant="dark" size="sm" icon="refresh" onClick={onAnalyze}>Retry</Button>} /></div>;
  return (
    <div className="col" style={{ gap: 16 }}>
      {header}
      <Card>
        {(maps.rating != null) && <div className="row" style={{ gap: 12, marginBottom: 12 }}>
          <div><div style={{ fontWeight: 800, fontSize: 28, letterSpacing: "-0.02em" }}>{maps.rating}</div><div className="row" style={{ gap: 1 }}>{[1, 2, 3, 4, 5].map((s) => <Icon key={s} name="star" size={13} style={{ color: s <= Math.round(maps.rating) ? "var(--color-warning)" : "var(--border-2)" }} />)}</div></div>
          <div style={{ borderInlineStart: "1px solid var(--border-1)", paddingInlineStart: 12 }}><div style={{ fontWeight: 700, fontSize: 14 }}>{maps.reviews ?? "—"}</div><div className="muted" style={{ fontSize: 12 }}>reviews</div></div>
        </div>}
        {maps.name && <KV k="Business name" v={maps.name} />}
        {maps.category && <KV k="Category" v={maps.category} />}
        {maps.address && <KV k="Address" v={maps.address} />}
        {maps.hours && <KV k="Hours" v={maps.hours} />}
        {maps.phone && <KV k="Phone" v={maps.phone} mono />}
      </Card>
      {maps.sentiment && <Card title="Customer sentiment">
        <p style={{ fontSize: 13.5, lineHeight: 1.55, color: "var(--fg-2)", marginBottom: 10 }} dir="auto">{maps.sentiment}</p>
        <TagRow items={maps.keywords} tone="purple" />
      </Card>}
      {maps.opportunity && <RecoBanner icon="target" title="Sales opportunity"><p style={{ fontSize: 13.5, lineHeight: 1.55 }} dir="auto">{maps.opportunity}</p></RecoBanner>}
    </div>
  );
}

function ProductsTab({ intel, c }) {
  const web = intel && intel.website;
  if (!web || web.status !== "analyzed" || ((web.products || []).length === 0 && (web.categories || []).length === 0))
    return <IntelEmpty icon="store" title="No products yet" body={c.website ? "Run Website Analysis to pull product categories and main products." : "No website on file."} />;
  return (
    <div className="col" style={{ gap: 16 }}>
      <Card title="Product categories"><TagRow items={web.categories} tone="purple" /></Card>
      <Card title="Main products">
        {(web.products || []).length ? <div className="col" style={{ gap: 0 }}>{web.products.map((p, i) => <div key={i} className="row" style={{ gap: 10, padding: "10px 0", borderBottom: i < web.products.length - 1 ? "1px solid var(--border-1)" : "none" }}><span className="opp" style={{ width: 32, height: 32, borderRadius: 8, background: "var(--bg-2)", color: "var(--fg-3)" }}><Icon name="tag" size={15} /></span><span style={{ fontSize: 13.5, fontWeight: 600 }} dir="auto">{p}</span></div>)}</div> : <span className="muted" style={{ fontSize: 13 }}>No individual products detected.</span>}
      </Card>
    </div>
  );
}

function AnglesTab({ c, intel, onCopyBrief, briefCopied, onSendCampaign, campaignBusy, onAddMemory, memState }) {
  const sales = (intel && intel.sales) || {};
  const web = intel && intel.website;
  const pains = (sales.painPoints && sales.painPoints.length ? sales.painPoints : (web && web.weaknesses)) || [];
  return (
    <div className="col" style={{ gap: 16 }}>
      <Card title="Pain points">
        {pains.length ? <div className="col" style={{ gap: 8 }}>{pains.map((x, i) => <div key={i} className="row" style={{ gap: 8, fontSize: 13 }}><Icon name="alert" size={15} style={{ color: "var(--color-orange)", flexShrink: 0, marginTop: 1 }} /><span style={{ color: "var(--fg-2)" }} dir="auto">{x}</span></div>)}</div> : <span className="muted" style={{ fontSize: 13 }}>Run Website Analysis to surface pain points.</span>}
      </Card>
      {sales.bestOpener && <Card title="Best opening message"><p dir="auto" style={{ fontSize: 13.5, lineHeight: 1.6, color: "var(--fg-1)", background: "var(--bg-2)", borderRadius: 10, padding: 12 }}>{sales.bestOpener}</p></Card>}
      {sales.objections && sales.objections.length > 0 && <Card title="Likely objections">
        <div className="col" style={{ gap: 8 }}>{sales.objections.map((o, i) => <div key={i} className="row" style={{ gap: 6, fontSize: 13 }}><Icon name="message" size={14} style={{ color: "var(--fg-3)", flexShrink: 0, marginTop: 2 }} /><span dir="auto">{o}</span></div>)}</div>
      </Card>}
      <RecoBanner icon="trophy" title="Suggested offer">
        <KV k="Recommended package" v={<Badge tone="dark">{sales.recommendedServiceLabel || "Discovery call"}</Badge>} />
        <KV k="Opportunity value" v={<OppBadge band={c.value} />} />
        {sales.recommendationReasons && sales.recommendationReasons[0] && <KV k="Why" v={sales.recommendationReasons[0]} />}
        {sales.followUpAngle && <div style={{ marginTop: 8, paddingTop: 8, borderTop: "1px solid var(--color-primary-tint)" }}><div className="muted" style={{ fontSize: 12.5, marginBottom: 4 }}>Suggested follow-up angle</div><p style={{ fontSize: 13, color: "var(--fg-1)", lineHeight: 1.5 }} dir="auto">{sales.followUpAngle}</p></div>}
        <div className="muted" style={{ fontSize: 12, marginTop: 10, lineHeight: 1.5 }}>{sales.googleMeet}{sales.maxabAIDiscount ? ` · MaxabAI discount: ${sales.maxabAIDiscount}` : ""}</div>
      </RecoBanner>
      {/* Phase 11 — every button wired to the real backend */}
      <div className="col" style={{ gap: 8 }}>
        <Button variant={briefCopied ? "subtle" : "dark"} icon={briefCopied ? "check" : "copy"} block onClick={onCopyBrief}>{briefCopied ? "Sales brief copied" : "Copy sales brief"}</Button>
        <div className="row" style={{ gap: 8 }}>
          <Button variant="primary" size="sm" icon="megaphone" disabled={campaignBusy} style={{ flex: 1 }} onClick={onSendCampaign}>{campaignBusy ? "Opening…" : "Send to campaign agent"}</Button>
          <Button variant="ghost" size="sm" icon={memState === "done" ? "check" : "sparkles"} disabled={memState === "saving"} style={{ flex: 1 }} onClick={onAddMemory}>{memState === "saving" ? "Saving…" : memState === "done" ? "Added to memory" : memState === "error" ? "Failed — retry" : "Add to agent memory"}</Button>
        </div>
      </div>
    </div>
  );
}

/* ---- Contact drawer ---------------------------------------------------- */
function DrawerHead({ title, sub, onClose, right }) {
  return (
    <div className="between" style={{ padding: "20px 24px", borderBottom: "1px solid var(--border-1)", background: "#fff", gap: 12, alignItems: "flex-start" }}>
      <div className="row" style={{ gap: 12, minWidth: 0, alignItems: "flex-start" }}>
        <button className="iconbtn" style={{ flexShrink: 0 }} onClick={onClose}><Icon name="x" size={20} /></button>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontWeight: 800, fontSize: 16, lineHeight: 1.3 }}>{title}</div>
          {sub && <div style={{ fontSize: 12, color: "var(--fg-4)", marginTop: 2 }}>{sub}</div>}
        </div>
      </div>
      <div style={{ flexShrink: 0, paddingTop: 4 }}>{right}</div>
    </div>
  );
}

function ContactDrawer({ contact, onClose }) {
  const { go, startRetarget, openAgent, startWizard } = useApp();
  const data = useStore();
  // resolve the live lead record so the drawer reflects workflow updates
  const c = data.CONTACTS.find((x) => x.id === contact.id) || contact;
  const camp = DATA.CAMPAIGNS.find((x) => x.id === c.campaign);
  const agent = DATA.AGENTS.find((a) => a.id === c.agentId) || DATA.AGENTS.find((a) => a.name === c.agent);
  const eligible = c.status === "followup" || (c.status === "interested" && c.heat < 60) || /day|week/.test(c.lastReply || "");
  const [brief, setBrief] = useState(false);
  const [done, setDone] = useState(false);
  const [tab, setTab] = useState("overview");
  const [menuOpen, setMenuOpen] = useState(false);
  const [editLead, setEditLead] = useState(false);
  const [confirmDelete, setConfirmDelete] = useState(false);
  const [copied, setCopied] = useState(false);
  // ---- Lead Intelligence (Phase 7/11) ----
  const [intel, setIntel] = useState(null);
  const [intelLoading, setIntelLoading] = useState(false);
  const [analyzing, setAnalyzing] = useState(false);     // website analysis in flight
  const [mapsBusy, setMapsBusy] = useState(false);
  const [briefCopied, setBriefCopied] = useState(false);
  const [memState, setMemState] = useState("idle");      // idle|saving|done|error
  const [campaignBusy, setCampaignBusy] = useState(false);

  const [webJob, setWebJob] = useState(null);                // async website-analysis job
  const jobTimer = React.useRef(null);

  const loadIntel = React.useCallback(() => {
    setIntelLoading(true);
    API.contacts.intelligence(c.id).then(setIntel).catch(() => {}).finally(() => setIntelLoading(false));
  }, [c.id]);
  React.useEffect(() => { loadIntel(); }, [loadIntel]);

  // Poll the async website-analysis job to completion so the drawer shows the
  // real status progress (queued → analyzing → completed/failed) and refreshes
  // the report the moment it's done — no manual reload needed.
  const pollWebJob = React.useCallback(() => {
    clearTimeout(jobTimer.current);
    const tick = () => API.contacts.websiteJob(c.id).then((r) => {
      const job = r && r.job; if (!job) return;
      setWebJob(job);
      if (["completed", "failed"].includes(job.status)) { setAnalyzing(false); loadIntel(); }
      else { setAnalyzing(true); jobTimer.current = setTimeout(tick, 1500); }
    }).catch(() => {});
    tick();
  }, [c.id, loadIntel]);
  // On open: if an analysis is already in flight for this lead, start polling.
  React.useEffect(() => {
    if (["queued", "analyzing"].includes(c.analysis)) pollWebJob();
    return () => clearTimeout(jobTimer.current);
  }, [c.id]);

  const analyzeWeb = async () => { setAnalyzing(true); setWebJob(null); try { await Actions.analyzeWebsite(c.id); pollWebJob(); } catch (e) { setAnalyzing(false); loadIntel(); } };
  const analyzeMapsFn = async () => { setMapsBusy(true); try { await Actions.analyzeMaps(c.id); loadIntel(); } catch (e) { loadIntel(); } finally { setMapsBusy(false); } };
  const copyBrief = async () => { try { const r = await API.contacts.salesBrief(c.id); copyText(r.brief || ""); setBriefCopied(true); setTimeout(() => setBriefCopied(false), 1800); } catch (e) {} };
  const addToMemory = async () => { setMemState("saving"); try { await API.contacts.addToAgentMemory(c.id); setMemState("done"); setTimeout(() => setMemState("idle"), 1800); } catch (e) { setMemState("error"); setTimeout(() => setMemState("idle"), 2000); } };
  const sendToCampaign = async () => {
    setCampaignBusy(true);
    try {
      const r = await API.contacts.toCampaign(c.id);
      startWizard({ group: { id: "lead-" + c.id, name: c.name, count: 1, contactIds: [c.id], src: "From lead", icon: "target", fromImport: true }, goal: r.recommendedService || "shopify" });
      onClose();
    } catch (e) { setCampaignBusy(false); }
  };

  const copyUrl = () => {
    copyText(`${location.origin}${location.pathname}#lead=${c.id}`);
    setCopied(true);
    setTimeout(() => setCopied(false), 1400);
  };
  const markLost = () => { setMenuOpen(false); Actions.updateLead(c.id, { status: "lost" }).catch(() => {}); };
  const markWon = () => { setMenuOpen(false); Actions.updateLead(c.id, { status: "won" }).catch(() => {}); };

  return (
    <Drawer onClose={onClose}>
      <DrawerHead title={c.name} sub={`${c.person || "—"} · ${[c.city, c.country].filter(Boolean).join(", ")}`} onClose={onClose}
        right={
          <div style={{ position: "relative" }}>
            <button className="iconbtn" onClick={() => setMenuOpen((v) => !v)} title="Lead actions"><Icon name="moreV" size={20} /></button>
            {menuOpen && (
              <>
                <div style={{ position: "fixed", inset: 0, zIndex: 60 }} onClick={() => setMenuOpen(false)} />
                <div style={{ position: "absolute", insetInlineEnd: 0, top: 44, zIndex: 61, background: "#fff", border: "1px solid var(--border-1)", borderRadius: 12, boxShadow: "var(--shadow-lg)", width: 208, overflow: "hidden", padding: 6 }}>
                  <button className="navitem" style={{ marginBottom: 0 }} onClick={() => { setMenuOpen(false); setEditLead(true); }}><Icon name="edit" size={16} />Edit lead</button>
                  <button className="navitem" style={{ marginBottom: 0 }} onClick={copyUrl}><Icon name={copied ? "check" : "link"} size={16} />{copied ? "Link copied" : "Copy lead URL"}</button>
                  {c.status !== "won" && <button className="navitem" style={{ marginBottom: 0, color: "var(--color-secondary)" }} onClick={markWon}><Icon name="trophy" size={16} />Mark as won</button>}
                  {c.status !== "lost" && <button className="navitem" style={{ marginBottom: 0 }} onClick={markLost}><Icon name="ban" size={16} />Mark as lost</button>}
                  <div className="divider" style={{ margin: "6px 4px" }} />
                  <button className="navitem" style={{ marginBottom: 0, color: "var(--color-danger)" }} onClick={() => { setMenuOpen(false); setConfirmDelete(true); }}><Icon name="trash" size={16} />Delete lead</button>
                </div>
              </>
            )}
          </div>
        } />

      {/* tabs: Overview · the unified Lead Intelligence (Phase 7) · Dynamic Workflow */}
      <div className="chipscroll" style={{ padding: "10px 16px", borderBottom: "1px solid var(--border-1)", background: "#fff", gap: 2 }}>
        {[
          { id: "overview", label: "Overview", icon: "user" },
          { id: "web", label: "Website", icon: "globe" },
          { id: "maps", label: "Google Maps", icon: "mapPin" },
          { id: "products", label: "Products", icon: "store" },
          { id: "angles", label: "Sales angles", icon: "target" },
          { id: "workflow", label: "Workflow", icon: "zap" },
        ].map((tb) => (
          <button key={tb.id} onClick={() => setTab(tb.id)} className="row" style={{ gap: 6, flexShrink: 0, padding: "7px 12px", borderRadius: 999, fontSize: 12.5, fontWeight: 600, whiteSpace: "nowrap", background: tab === tb.id ? "var(--color-primary-tint-soft)" : "transparent", color: tab === tb.id ? "var(--color-secondary)" : "var(--fg-3)", border: "none", cursor: "pointer" }}>
            <Icon name={tb.icon} size={14} />{tb.label}
          </button>
        ))}
      </div>

      <div style={{ flex: 1, overflowY: "auto", padding: 24, display: "flex", flexDirection: "column", gap: 16 }}>
        {tab === "web" && <WebsiteTab c={c} intel={intel} busy={analyzing} loading={intelLoading} onAnalyze={analyzeWeb} job={webJob} />}
        {tab === "maps" && <MapsTab c={c} intel={intel} busy={mapsBusy} loading={intelLoading} onAnalyze={analyzeMapsFn} />}
        {tab === "products" && <ProductsTab intel={intel} c={c} />}
        {tab === "angles" && <AnglesTab c={c} intel={intel} onCopyBrief={copyBrief} briefCopied={briefCopied} onSendCampaign={sendToCampaign} campaignBusy={campaignBusy} onAddMemory={addToMemory} memState={memState} />}
        {tab === "overview" ? (
          <>
            <div className="row wrap" style={{ gap: 8 }}>
              <StatusPill status={crmOptKey(c.status)} />
              {crmOptKey(c.stage) && <Badge tone="dark">{crmOptText(c.stage)}</Badge>}
              <Badge tone="neutral" dot={priorityMeta(c.priority).c}>{priorityMeta(c.priority).label} priority</Badge>
              <Badge tone="neutral"><Icon name="store" size={13} />{c.platform}</Badge>
              {(c.website || c.analysis) && <AnalysisChip status={analyzing ? "analyzing" : c.analysis} />}
            </div>

            {/* AI recommendation — the hero of the drawer */}
            <div style={{ background: "var(--color-primary-tint-soft)", border: "1px solid var(--color-primary-tint)", borderRadius: 16, padding: 18 }}>
              <div className="row" style={{ gap: 8, marginBottom: 8 }}>
                <Icon name="sparkles" size={18} style={{ color: "var(--color-secondary)" }} />
                <b style={{ color: "var(--color-secondary)", fontSize: 13 }}>AI recommendation</b>
              </div>
              <div style={{ fontSize: 14, lineHeight: 1.55, color: "var(--fg-1)" }}>{c.reco}</div>
              <div className="row wrap" style={{ gap: 8, marginTop: 14 }}>
                <Button variant="primary" size="sm" icon="sparkles" onClick={() => setBrief(true)}>Brief {c.agent} to follow up</Button>
                <Button variant="ghost" size="sm" icon="zap" onClick={() => setTab("workflow")}>Run workflow</Button>
                <Button variant="ghost" size="sm" icon="message" onClick={() => go("conversations")}>Open chat</Button>
              </div>
            </div>

            {/* Next action */}
            <Card>
              <div className="between">
                <div className="row" style={{ gap: 10 }}>
                  <Icon name="target" size={18} style={{ color: "var(--fg-3)" }} />
                  <div><div style={{ fontWeight: 700, fontSize: 14 }}>{c.next}</div><div style={{ fontSize: 12, color: "var(--fg-4)" }}>Due {c.nextAt}</div></div>
                </div>
                {done
                  ? <Badge tone="green" dot="#22C55E">Done</Badge>
                  : <Button variant="primary" size="sm" onClick={() => setBrief(true)}>Do it</Button>}
              </div>
            </Card>

            {/* CRM status / pipeline stage — manual control */}
            <LeadCrmCard contact={c} />

            {/* Manual follow-up scheduling */}
            <LeadFollowUps contact={c} />

            {/* Google Meet scheduler (Phase 5) */}
            <MeetingCard contact={c} />

            {/* Assigned agent — jump to brief/train */}
            <Card>
              <div className="between">
                <button className="row" style={{ gap: 12, background: "none", border: "none", cursor: "pointer", textAlign: "start", padding: 0 }} onClick={() => openAgent(agent)}>
                  <Avatar name={c.agent} size="lg" color={agent?.color} />
                  <div><div style={{ fontWeight: 700, fontSize: 14 }}>{c.agent}</div><div style={{ fontSize: 12, color: "var(--fg-4)" }}>{agent?.role} · handling this lead</div></div>
                </button>
                <Button variant="ghost" size="sm" iconEnd="chevronRight" onClick={() => openAgent(agent)}>View agent</Button>
              </div>
            </Card>

            {/* Sales opportunity — AI-owned score + win probability (Phase 5) */}
            {(typeof c.opportunityScore === "number" || c.sentiment) && (
              <Card title="Sales opportunity">
                <div className="row" style={{ gap: 6, marginTop: -4, marginBottom: 12, fontSize: 12, color: "var(--color-secondary)", fontWeight: 600 }}>
                  <Icon name="sparkles" size={13} /> Maintained automatically by {c.agent || "the AI"}
                </div>
                <div className="col" style={{ gap: 14 }}>
                  {typeof c.opportunityScore === "number" && <div className="between"><span className="muted" style={{ fontSize: 13 }}>Opportunity score</span><span className="row" style={{ gap: 8 }}><ScoreBar value={c.opportunityScore} color="var(--color-secondary)" />{c.opportunityBand && <Badge tone="neutral">{c.opportunityBand}</Badge>}</span></div>}
                  {typeof c.winProbability === "number" && <div className="between"><span className="muted" style={{ fontSize: 13 }}>Win probability</span><span style={{ fontWeight: 700, fontSize: 13 }}>{c.winProbability}%</span></div>}
                  {c.sentiment && <div className="between"><span className="muted" style={{ fontSize: 13 }}>Sentiment</span><Badge tone={SENTIMENT_TONE[c.sentiment] || "neutral"}>{c.sentimentLabel || c.sentiment}</Badge></div>}
                  {c.nextBestAction && <div className="between" style={{ alignItems: "flex-start" }}><span className="muted" style={{ fontSize: 13, flexShrink: 0 }}>Next best action</span><span style={{ fontWeight: 600, fontSize: 13, textAlign: "end", maxWidth: "64%" }}>{c.nextBestAction}</span></div>}
                </div>
              </Card>
            )}

            {/* Lead signals — every signal the agent reasons over */}
            <Card title="Lead signals">
              <div className="col" style={{ gap: 14, marginTop: 4 }}>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Trust score</span><ScoreBar value={c.trust} /></div>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Conversation heat</span><ScoreBar value={c.heat} color="var(--color-orange)" /></div>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Opportunity value</span><OppBadge band={c.value} /></div>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Priority</span><Badge tone="neutral" dot={priorityMeta(c.priority).c}>{priorityMeta(c.priority).label}</Badge></div>
                <div className="between"><span className="muted" style={{ fontSize: 13 }}>Platform</span><span style={{ fontWeight: 600, fontSize: 13 }}>{c.platform}</span></div>
                {c.service && <div className="between"><span className="muted" style={{ fontSize: 13 }}>Service interest</span><span style={{ fontWeight: 600, fontSize: 13, textTransform: "capitalize" }}>{c.service}</span></div>}
                {Array.isArray(c.interests) && c.interests.length > 0 && <div className="between"><span className="muted" style={{ fontSize: 13 }}>Interests</span><span style={{ fontWeight: 600, fontSize: 13, textAlign: "end" }}>{c.interests.join(", ")}</span></div>}
                {Array.isArray(c.objections) && c.objections.length > 0 && <div className="between"><span className="muted" style={{ fontSize: 13 }}>Objections</span><span style={{ fontWeight: 600, fontSize: 13, color: "var(--color-danger)", textAlign: "end" }}>{c.objections.map((o) => OBJECTION_LABEL[o] || o).join(", ")}</span></div>}
              </div>
            </Card>

            {/* AI activity timeline — every CRM change the agent made automatically */}
            {Array.isArray(c.activities) && c.activities.length > 0 && (
              <Card title="AI activity">
                <div className="col" style={{ gap: 12, marginTop: 4 }}>
                  {c.activities.slice().reverse().slice(0, 12).map((a, i) => (
                    <div key={a.id || i} className="row" style={{ gap: 10, alignItems: "flex-start" }}>
                      <Icon name={ACTIVITY_ICON[a.type] || "sparkles"} size={14} style={{ color: "var(--color-secondary)", marginTop: 2, flexShrink: 0 }} />
                      <div style={{ minWidth: 0 }}>
                        <div style={{ fontSize: 13, color: "var(--fg-1)", lineHeight: 1.45 }}>{a.text}</div>
                        <div style={{ fontSize: 11, color: "var(--fg-4)" }}>{a.by || "AI"}{a.at ? " · " + new Date(a.at).toLocaleString() : ""}</div>
                      </div>
                    </div>
                  ))}
                </div>
              </Card>
            )}

            {/* BANT qualification — explicit lead intelligence, updated by text
                conversations, voice-note transcripts, website intelligence & campaign replies */}
            <Card title="BANT qualification">
              {(() => {
                const b = c.bant || {};
                const ROWS = [["budget", "Budget", "dollar"], ["authority", "Authority", "user"], ["need", "Need", "target"], ["timeline", "Timeline", "clock"]];
                const known = ROWS.filter(([k]) => b[k] && b[k].value && b[k].value !== "unknown").length;
                return (
                  <>
                    <div className="between" style={{ marginTop: -4, marginBottom: 12 }}>
                      <span className="row" style={{ gap: 6, fontSize: 12, color: "var(--color-secondary)", fontWeight: 600 }}><Icon name="sparkles" size={13} />From chats, voice notes & discovery</span>
                      <Badge tone={known >= 3 ? "green" : known >= 1 ? "lime" : "neutral"} dot={known >= 1 ? "#22C55E" : "#9CA3AF"}>{known}/4 captured</Badge>
                    </div>
                    <div className="col" style={{ gap: 12 }}>
                      {ROWS.map(([k, label, icon]) => {
                        const f = b[k];
                        const set = f && f.value && f.value !== "unknown";
                        return (
                          <div key={k} className="between" style={{ alignItems: "flex-start" }}>
                            <span className="row" style={{ gap: 7, fontSize: 13, color: "var(--fg-3)", flexShrink: 0 }}><Icon name={icon} size={14} />{label}</span>
                            <div style={{ textAlign: "end", maxWidth: "62%" }}>
                              {set ? <>
                                <div style={{ fontWeight: 700, fontSize: 13 }} dir="auto">{f.label || f.value}</div>
                                <div style={{ fontSize: 11, color: "var(--fg-4)" }}>{f.source ? `via ${f.source}` : ""}{Number.isFinite(f.confidence) ? ` · ${Math.round(f.confidence * 100)}%` : ""}</div>
                              </> : <span className="muted" style={{ fontSize: 12.5 }}>Not captured yet</span>}
                            </div>
                          </div>
                        );
                      })}
                    </div>
                  </>
                );
              })()}
            </Card>

            {/* Lead memory — persisted facts that shape every future reply */}
            <Card title="Lead memory">
              <div className="row" style={{ gap: 6, marginTop: -4, marginBottom: 12, fontSize: 12, color: "var(--color-secondary)", fontWeight: 600 }}>
                <Icon name="sparkles" size={13} /> Affecting future replies
              </div>
              {(c.notes && c.notes.length) ? (
                <div className="col" style={{ gap: 12 }}>
                  {c.notes.slice().reverse().map((n, i) => (
                    <div key={n.id || i} style={{ borderInlineStart: "2px solid var(--color-primary-tint)", paddingInlineStart: 10 }}>
                      <div style={{ fontSize: 13, color: "var(--fg-1)", lineHeight: 1.5 }}>{n.text || n}</div>
                      <div className="row" style={{ gap: 8, marginTop: 4, fontSize: 11, color: "var(--fg-4)" }}>
                        <span>{n.by || "You"}</span>{n.at && <span>· {new Date(n.at).toLocaleDateString()}</span>}<Badge tone="neutral">note</Badge>
                      </div>
                    </div>
                  ))}
                </div>
              ) : (
                <div className="muted" style={{ fontSize: 13 }}>No memory yet — notes &amp; briefs you add here shape the agent's future replies to this lead.</div>
              )}
              <Button variant="ghost" size="sm" icon="sparkles" style={{ marginTop: 14 }} onClick={() => setBrief(true)}>Brief agent</Button>
            </Card>

            {/* Lead profile — the imported/known facts (platform, website, maps,
                category, source) must ALL surface here for an imported lead. */}
            <Card title="Lead profile">
              <div className="col" style={{ gap: 10, marginTop: 4, fontSize: 13 }}>
                <div className="between"><span className="muted">Platform</span><span style={{ fontWeight: 600 }}>{c.platform}</span></div>
                {c.category && <div className="between"><span className="muted">Category</span><span style={{ fontWeight: 600 }}>{c.category}</span></div>}
                {c.website && <div className="between" style={{ gap: 12 }}><span className="muted">Website</span><a href={/^https?:/i.test(c.website) ? c.website : "https://" + c.website} target="_blank" rel="noreferrer" style={{ fontWeight: 600, color: "var(--color-secondary)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", maxWidth: "62%" }}>{String(c.website).replace(/^https?:\/\//, "")}</a></div>}
                {(c.gmaps || c.googleMapsUrl) && <div className="between" style={{ gap: 12 }}><span className="muted">Google Maps</span><a href={c.gmaps || c.googleMapsUrl} target="_blank" rel="noreferrer" style={{ fontWeight: 600, color: "var(--color-secondary)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", maxWidth: "62%" }}>{String(c.gmaps || c.googleMapsUrl).replace(/^https?:\/\//, "")}</a></div>}
                {c.instagram && <div className="between"><span className="muted">Social</span><span style={{ fontWeight: 600 }}>{c.instagram}</span></div>}
                <div className="between"><span className="muted">Phone</span><span style={{ fontWeight: 600 }} dir="ltr">{c.phone}</span></div>
                {(c.source || c.discoverySource) && <div className="between"><span className="muted">Source</span><span style={{ fontWeight: 600 }}>{c.source || c.discoverySource}</span></div>}
              </div>
            </Card>

            {/* Conversation summary */}
            <Card title="Conversation summary">
              <p style={{ fontSize: 14, lineHeight: 1.6, color: "var(--fg-2)" }}>{c.summary}</p>
              <div className="row" style={{ gap: 8, marginTop: 12, fontSize: 12, color: "var(--fg-4)" }}>
                <Avatar name={c.agent} size="sm" /><span>Handled by <b style={{ color: "var(--fg-2)" }}>{c.agent}</b>{camp ? ` · ${camp.name}` : ""}</span>
              </div>
            </Card>

            {/* Retargeting */}
            <Card>
              <div className="between">
                <div className="row" style={{ gap: 10 }}>
                  <Icon name="refresh" size={18} style={{ color: eligible ? "var(--color-blue)" : "var(--fg-disabled)" }} />
                  <div>
                    <div style={{ fontWeight: 700, fontSize: 14 }}>Retargeting</div>
                    <div style={{ fontSize: 12, color: "var(--fg-4)" }}>{eligible ? "Eligible — silent and worth re-engaging" : "Not eligible yet"}</div>
                  </div>
                </div>
                {eligible ? <Button variant="ghost" size="sm" onClick={startRetarget}>Add to retarget</Button> : <Badge tone="neutral">—</Badge>}
              </div>
            </Card>
          </>
        ) : null}
        {tab === "workflow" && <WorkflowPanel contact={c} agent={agent} />}
      </div>
      {brief && <BriefAgentModal contact={c} agent={agent} onClose={() => setBrief(false)} onSent={() => { setBrief(false); setDone(true); }} />}
      {editLead && <AddLeadModal lead={c} onClose={() => setEditLead(false)} />}
      {confirmDelete && <DeleteLeadModal contact={c} onClose={() => setConfirmDelete(false)} onDeleted={() => { setConfirmDelete(false); onClose(); }} />}
    </Drawer>
  );
}

/* ---- Retarget overlay -------------------------------------------------- */
const RETARGET_RULES = [
  { id: "warm", label: "All warm leads", test: (c) => ["interested", "proposal", "followup"].includes(c.status) },
  { id: "interested", label: "Interested, gone quiet", test: (c) => c.status === "interested" },
  { id: "proposal", label: "Proposal, no reply", test: (c) => c.status === "proposal" },
  { id: "followup", label: "Follow-ups due", test: (c) => c.status === "followup" },
];

function RetargetOverlay({ onClose, onCreateCampaign }) {
  const [tab, setTab] = useState("crm"); // "crm" | "campaign"
  // ---- CRM tab (client-side rules over the live CRM) ----
  const [rule, setRule] = useState("warm");
  const matches = DATA.CONTACTS.filter(RETARGET_RULES.find((r) => r.id === rule).test);
  const [selected, setSelected] = useState(() => new Set(matches.map((c) => c.id)));
  const changeRule = (id) => { setRule(id); const m = DATA.CONTACTS.filter(RETARGET_RULES.find((r) => r.id === id).test); setSelected(new Set(m.map((c) => c.id))); };
  const toggle = (id) => setSelected((s) => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });
  const count = matches.filter((c) => selected.has(c.id)).length;
  const createCrm = () => {
    const contactIds = matches.filter((c) => selected.has(c.id)).map((c) => c.id);
    const grp = { id: "retarget", name: "Retarget · " + RETARGET_RULES.find((r) => r.id === rule).label, count, contactIds, src: "From CRM", icon: "refresh", fromImport: true };
    onCreateCampaign && onCreateCampaign(grp);
  };

  // ---- Campaign tab (finished-campaign rules from the backend) ----
  const [camps, setCamps] = useState(null);
  const [campRules, setCampRules] = useState([]);
  const [campId, setCampId] = useState("");
  const [cRule, setCRule] = useState("");
  const [preview, setPreview] = useState(null);
  const [busy, setBusy] = useState(false);
  const [created, setCreated] = useState(null);
  React.useEffect(() => { if (tab === "campaign" && camps === null) API.retargeting.campaigns().then((r) => setCamps(r.campaigns || [])).catch(() => setCamps([])); }, [tab]);
  const selCampaign = (camps || []).find((c) => c.id === campId) || null;
  const pickCampaign = (id) => {
    setCampId(id); setCRule(""); setPreview(null); setCreated(null);
    if (!id) { setCampRules([]); return; }
    API.retargeting.campaignRules(id).then((r) => setCampRules(r.rules || [])).catch(() => setCampRules([]));
  };
  const pickRule = (rid) => {
    setCRule(rid); setPreview(null); setCreated(null);
    API.retargeting.preview({ source: "campaign", campaignId: campId, ruleId: rid }).then(setPreview).catch(() => setPreview({ leads: [] }));
  };
  const createCampaignRetarget = () => {
    setBusy(true);
    API.retargeting.createCampaign({ source: "campaign", campaignId: campId, ruleId: cRule })
      .then((r) => setCreated(r)).catch((e) => setCreated({ ok: false, error: e.message })).finally(() => setBusy(false));
  };

  return (
    <Scrim onClose={onClose}>
      <div className="modal" style={{ width: 860, maxWidth: "94vw", height: "86vh", maxHeight: 720, display: "flex", flexDirection: "column", padding: 0 }} onClick={(e) => e.stopPropagation()}>
        <div className="between" style={{ padding: "18px 24px", borderBottom: "1px solid var(--border-1)" }}>
          <div className="row" style={{ gap: 12 }}>
            <span className="opp" style={{ width: 40, height: 40, borderRadius: 12, background: "var(--color-blue-soft)", color: "var(--color-blue)" }}><Icon name="refresh" size={20} /></span>
            <div><div style={{ fontWeight: 800, fontSize: 16 }}>Retarget leads</div><div style={{ fontSize: 12, color: "var(--fg-4)" }}>Re-engage quiet CRM leads, or leads from a finished campaign</div></div>
          </div>
          <button className="iconbtn" onClick={onClose}><Icon name="x" size={20} /></button>
        </div>

        {/* tabs */}
        <div className="row" style={{ gap: 4, padding: "10px 24px 0" }}>
          {[["crm", "From CRM", "users"], ["campaign", "From campaign", "megaphone"]].map(([k, lbl, ic]) => (
            <button key={k} onClick={() => setTab(k)} className="row" style={{ gap: 6, padding: "8px 14px", fontSize: 13, fontWeight: 700, borderRadius: "10px 10px 0 0", cursor: "pointer", border: "none", borderBottom: tab === k ? "2px solid var(--color-secondary)" : "2px solid transparent", color: tab === k ? "var(--color-secondary)" : "var(--fg-3)", background: "transparent" }}><Icon name={ic} size={14} />{lbl}</button>
          ))}
        </div>

        {tab === "crm" ? (
          <>
            <div className="row wrap" style={{ gap: 8, padding: "16px 24px", borderBottom: "1px solid var(--border-1)", background: "var(--bg-2)" }}>
              {RETARGET_RULES.map((r) => {
                const n = DATA.CONTACTS.filter(r.test).length; const on = rule === r.id;
                return (<button key={r.id} onClick={() => changeRule(r.id)} style={{ height: 34, padding: "0 14px", borderRadius: 999, fontSize: 13, fontWeight: 600, border: "1px solid " + (on ? "var(--color-secondary)" : "var(--border-2)"), background: on ? "var(--color-secondary)" : "#fff", color: on ? "#fff" : "var(--fg-2)" }}>{r.label} <span style={{ opacity: 0.6, marginInlineStart: 4 }}>{n}</span></button>);
              })}
            </div>
            <div style={{ flex: 1, overflowY: "auto", padding: 24 }}>
              {matches.length === 0 ? (
                <EmptyState icon="refresh" title="No leads match this rule" body="Try another rule above — these change as your conversations progress." />
              ) : (
                <Card flush>
                  <div className="between" style={{ padding: "12px 16px", borderBottom: "1px solid var(--border-1)" }}>
                    <b style={{ fontSize: 13 }}>{matches.length} leads match</b>
                    <button className="btn btn--subtle btn--sm" onClick={() => setSelected(count === matches.length ? new Set() : new Set(matches.map((c) => c.id)))}>{count === matches.length ? "Clear all" : "Select all"}</button>
                  </div>
                  <table className="table"><tbody>
                    {matches.map((c) => (
                      <tr key={c.id} onClick={() => toggle(c.id)} style={{ cursor: "pointer" }}>
                        <td style={{ width: 44 }}><span style={{ width: 20, height: 20, borderRadius: 6, display: "inline-flex", alignItems: "center", justifyContent: "center", border: "1.5px solid " + (selected.has(c.id) ? "var(--color-secondary)" : "var(--border-2)"), background: selected.has(c.id) ? "var(--color-secondary)" : "#fff", color: "#fff" }}>{selected.has(c.id) && <Icon name="check" size={13} />}</span></td>
                        <td><div className="row" style={{ gap: 10 }}><Avatar name={c.person} size="sm" /><div><div style={{ fontWeight: 700, fontSize: 13.5 }}>{c.name}</div><div style={{ fontSize: 11, color: "var(--fg-4)" }}>{c.city} · {c.agent}</div></div></div></td>
                        <td><StatusPill status={crmOptKey(c.status)} /></td>
                        <td><OppBadge band={c.value} /></td>
                        <td style={{ fontSize: 12, color: /day|week/.test(c.lastReply) ? "var(--color-warning)" : "var(--fg-4)", fontWeight: /day|week/.test(c.lastReply) ? 700 : 400 }}><span className="row" style={{ gap: 5 }}><Icon name="clock" size={13} />{c.lastReply}</span></td>
                      </tr>
                    ))}
                  </tbody></table>
                </Card>
              )}
              <div className="row" style={{ gap: 10, marginTop: 16, background: "var(--color-primary-tint-soft)", border: "1px solid var(--color-primary-tint)", borderRadius: 12, padding: 14, alignItems: "flex-start" }}>
                <Icon name="sparkles" size={18} style={{ color: "var(--color-secondary)", flexShrink: 0, marginTop: 1 }} />
                <span style={{ fontSize: 13, color: "var(--fg-2)", lineHeight: 1.5 }}>The agent writes a fresh, low-pressure message for each lead — no repeated pitches. You approve before anything sends.</span>
              </div>
            </div>
            <div className="between" style={{ padding: "16px 24px", borderTop: "1px solid var(--border-1)" }}>
              <span className="subtle" style={{ fontSize: 13 }}><b style={{ color: "var(--fg-1)" }}>{count}</b> selected</span>
              <div className="row" style={{ gap: 10 }}>
                <Button variant="ghost" onClick={onClose}>Cancel</Button>
                <Button variant="primary" icon="megaphone" disabled={count === 0} onClick={createCrm}>Create retargeting campaign</Button>
              </div>
            </div>
          </>
        ) : (
          <>
            <div style={{ flex: 1, overflowY: "auto", padding: 24, display: "flex", flexDirection: "column", gap: 16 }}>
              {/* finished campaign selector */}
              <Field label="Finished campaign">
                <select className="select" value={campId} onChange={(e) => pickCampaign(e.target.value)}>
                  <option value="">{camps === null ? "Loading campaigns…" : (camps.length ? "Select a campaign…" : "No launched campaigns yet")}</option>
                  {(camps || []).map((c) => <option key={c.id} value={c.id}>{c.name} — {c.metrics.recipients} reached{c.finished ? " · finished" : ""}</option>)}
                </select>
              </Field>
              {/* campaign metrics */}
              {selCampaign && (
                <div className="row wrap" style={{ gap: 10 }}>
                  {[["Reached", selCampaign.metrics.recipients], ["Sent", selCampaign.metrics.sent], ["Replied", selCampaign.metrics.replied], ["No reply", selCampaign.metrics.noReply], ["Meetings", selCampaign.metrics.meetings], ["Failed", selCampaign.metrics.failed]].map(([k, v]) => (
                    <div key={k} style={{ flex: "1 1 96px", background: "var(--bg-2)", border: "1px solid var(--border-1)", borderRadius: 10, padding: "10px 12px" }}><div style={{ fontWeight: 800, fontSize: 18 }}>{v}</div><div className="muted" style={{ fontSize: 11.5 }}>{k}</div></div>
                  ))}
                </div>
              )}
              {/* retarget rules */}
              {campId && (
                <div className="row wrap" style={{ gap: 8 }}>
                  {campRules.map((r) => { const on = cRule === r.id; return (
                    <button key={r.id} onClick={() => pickRule(r.id)} title={r.description} style={{ height: 34, padding: "0 14px", borderRadius: 999, fontSize: 13, fontWeight: 600, border: "1px solid " + (on ? "var(--color-secondary)" : "var(--border-2)"), background: on ? "var(--color-secondary)" : "#fff", color: on ? "#fff" : "var(--fg-2)" }}>{r.label} <span style={{ opacity: 0.6, marginInlineStart: 4 }}>{r.count}</span></button>
                  ); })}
                </div>
              )}
              {/* matched-leads preview with full re-engagement context */}
              {created ? (
                created.ok ? (
                  <div className="col" style={{ gap: 8, alignItems: "center", padding: "20px 0", background: "var(--color-success-soft)", border: "1px solid #A7F3D0", borderRadius: 12 }}>
                    <span className="opp" style={{ width: 48, height: 48, borderRadius: 14, background: "#fff", color: "#15803D" }}><Icon name="checkcircle" size={24} /></span>
                    <div style={{ fontWeight: 700 }}>Created “{created.campaign.name}”</div>
                    <div className="muted" style={{ fontSize: 12.5, textAlign: "center", maxWidth: 420 }}>{created.count} lead{created.count === 1 ? "" : "s"} added with their previous message, objection and recommended next action. Open it in Campaigns to review and launch.</div>
                  </div>
                ) : <div className="row" style={{ gap: 8, background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 10, padding: "10px 12px", fontSize: 13 }}><Icon name="alert" size={15} />{created.error || "Couldn't create the campaign."}</div>
              ) : preview ? (
                preview.leads && preview.leads.length ? (
                  <Card flush>
                    <div className="between" style={{ padding: "12px 16px", borderBottom: "1px solid var(--border-1)" }}><b style={{ fontSize: 13 }}>{preview.count} matched lead{preview.count === 1 ? "" : "s"}</b><span className="muted" style={{ fontSize: 12 }}>{preview.ruleLabel}</span></div>
                    <div className="col" style={{ gap: 0 }}>
                      {preview.leads.slice(0, 50).map((l) => (
                        <div key={l.contactId} style={{ padding: "12px 16px", borderBottom: "1px solid var(--border-1)" }}>
                          <div className="between" style={{ gap: 8 }}><div style={{ fontWeight: 700, fontSize: 13.5 }}>{l.name || l.contactId}</div>{l.previousObjection && <Badge tone="orange">{l.previousObjection}</Badge>}</div>
                          {l.previousMessage && <div className="muted" style={{ fontSize: 12, marginTop: 4 }} dir="auto">Last message: “{String(l.previousMessage).slice(0, 120)}{String(l.previousMessage).length > 120 ? "…" : ""}”</div>}
                          {l.recommendedNextAction && <div style={{ fontSize: 12, marginTop: 4, color: "var(--color-secondary)" }} dir="auto"><Icon name="target" size={12} /> {l.recommendedNextAction}</div>}
                        </div>
                      ))}
                    </div>
                  </Card>
                ) : <EmptyState icon="refresh" title="No leads match this rule" body="Pick a different rule — the counts above show how many match each one." />
              ) : (
                <EmptyState icon="megaphone" title={campId ? "Pick a rule" : "Pick a finished campaign"} body={campId ? "Choose a retarget rule above to preview matched leads and their history." : "Select a campaign you've already launched to re-engage its leads."} />
              )}
            </div>
            <div className="between" style={{ padding: "16px 24px", borderTop: "1px solid var(--border-1)" }}>
              <span className="subtle" style={{ fontSize: 13 }}>{preview && preview.leads ? <><b style={{ color: "var(--fg-1)" }}>{preview.count}</b> matched</> : "—"}</span>
              <div className="row" style={{ gap: 10 }}>
                <Button variant="ghost" onClick={onClose}>{created && created.ok ? "Done" : "Cancel"}</Button>
                {!(created && created.ok) && <Button variant="primary" icon="megaphone" disabled={!cRule || !preview || !(preview.leads || []).length || busy} onClick={createCampaignRetarget}>{busy ? "Creating…" : "Create retargeting campaign"}</Button>}
              </div>
            </div>
          </>
        )}
      </div>
    </Scrim>
  );
}

/* ---- Brief the agent --------------------------------------------------- */
const BRIEF_INTENTS = [
  { id: "offer", label: "Make an offer", icon: "tag", text: "Reach out again with a special offer for them — describe it here." },
  { id: "info", label: "Share new info", icon: "fileText", text: "Send them this new information: " },
  { id: "followup", label: "Gentle follow-up", icon: "clock", text: "Send a short, low-pressure follow-up to check in — no new pitch." },
  { id: "reintro", label: "Re-introduce", icon: "refresh", text: "Re-introduce yourself and remind them of the value we offer." },
];
const BRIEF_TIMING = [
  { id: "now", label: "Right away" },
  { id: "2d", label: "In 2 days" },
  { id: "week", label: "In a week" },
];

function BriefAgentModal({ contact: c, agent, onClose, onSent }) {
  const [intent, setIntent] = useState("offer");
  const [text, setText] = useState(BRIEF_INTENTS[0].text);
  const [timing, setTiming] = useState("now");
  const [link, setLink] = useState("");
  const [sent, setSent] = useState(false);
  const [sending, setSending] = useState(false);
  const [err, setErr] = useState(null);
  const [prior, setPrior] = useState([]);
  const base = trainingFor(agent?.id || "");
  const pickIntent = (i) => { setIntent(i.id); setText(i.text); };

  // load previous briefs for this lead (lead memory the agent will consume)
  React.useEffect(() => {
    let alive = true;
    API.briefs.list(`leadId=${c.id}`).then((r) => { if (alive) setPrior(r.briefs || []); }).catch(() => {});
    return () => { alive = false; };
  }, [c.id]);

  const send = () => {
    if (!text.trim() || sending) return;
    const timingLabel = (BRIEF_TIMING.find((x) => x.id === timing) || {}).label || "Right away";
    const linkObj = base.links.find((l) => l.url === link);
    const instruction = [
      text.trim(),
      linkObj ? `Send this link: ${linkObj.label} (${linkObj.url}).` : "",
      `Timing: ${timingLabel}.`,
    ].filter(Boolean).join(" ");
    setSending(true); setErr(null);
    API.briefs.create({ leadId: c.id, agentId: agent?.id || null, scope: "lead", instruction, priority: intent === "offer" ? "high" : "medium", createdBy: "You" })
      .then(() => { setSent(true); setTimeout(() => onSent && onSent(), 1200); })
      .catch((e) => { setErr(e.message || "Could not send brief"); })
      .finally(() => setSending(false));
  };

  return (
    <Modal onClose={onClose} style={{ width: 540, display: "flex", flexDirection: "column", maxHeight: "90vh", overflow: "hidden", padding: 0 }}>
      <div className="between" style={{ padding: "18px 22px", borderBottom: "1px solid var(--border-1)", flexShrink: 0 }}>
        <div className="row" style={{ gap: 12 }}>
          <Avatar name={agent?.name} color={agent?.color} />
          <div><div style={{ fontWeight: 800, fontSize: 16 }}>Brief {agent?.name}</div><div style={{ fontSize: 12, color: "var(--fg-4)" }}>Tell the agent how to reach {c.name} again</div></div>
        </div>
        <button className="iconbtn" onClick={onClose}><Icon name="x" size={20} /></button>
      </div>

      {sent ? (
        <div style={{ padding: "40px 24px", textAlign: "center", overflowY: "auto", flex: 1 }}>
          <span className="opp" style={{ width: 64, height: 64, borderRadius: 18, background: "var(--color-primary)", color: "var(--color-secondary)", margin: "0 auto 16px" }}><Icon name="checkcircle" size={32} /></span>
          <div style={{ fontWeight: 700, fontSize: 15 }}>Briefed {agent?.name}</div>
          <p className="muted" style={{ fontSize: 13, maxWidth: 360, margin: "8px auto 0" }}>The agent will reach out to {c.name} {BRIEF_TIMING.find((x) => x.id === timing).label.toLowerCase()} and send the draft to your approval queue.</p>
        </div>
      ) : (
        <>
        <div style={{ padding: 22, overflowY: "auto", flex: 1 }}>
          {prior.length > 0 && (
            <div style={{ marginBottom: 16, border: "1px solid var(--border-1)", borderRadius: 12, overflow: "hidden" }}>
              <div className="row" style={{ gap: 8, padding: "10px 12px", background: "var(--bg-2)" }}><Icon name="clipboard" size={14} style={{ color: "var(--fg-3)" }} /><b style={{ fontSize: 12.5 }}>Lead memory · {prior.length} previous brief{prior.length > 1 ? "s" : ""}</b></div>
              <div style={{ maxHeight: 120, overflowY: "auto" }}>
                {prior.slice(0, 4).map((b) => (
                  <div key={b.id} style={{ padding: "8px 12px", borderTop: "1px solid var(--border-1)", fontSize: 12 }}>
                    <div style={{ color: "var(--fg-2)" }} dir="auto">{b.instruction}</div>
                    <div className="row" style={{ gap: 6, marginTop: 3 }}><Badge tone={b.status === "active" ? "lime" : "neutral"}>{b.status}</Badge><span style={{ fontSize: 11, color: "var(--fg-disabled)" }}>{b.createdBy}</span></div>
                  </div>
                ))}
              </div>
            </div>
          )}
          <div className="field__label" style={{ marginBottom: 8 }}>What should the agent do?</div>
          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 16 }}>
            {BRIEF_INTENTS.map((i) => (
              <button key={i.id} className={"optcard" + (intent === i.id ? " is-selected" : "")} style={{ padding: 12 }} onClick={() => pickIntent(i)}>
                <span className="optcard__icon" style={{ width: 32, height: 32, background: "var(--bg-2)", color: "var(--color-secondary)" }}><Icon name={i.icon} size={16} /></span>
                <div style={{ flex: 1 }}><b style={{ fontSize: 13 }}>{i.label}</b></div>
                {intent === i.id && <Icon name="checkcircle" size={16} style={{ color: "var(--color-secondary)" }} />}
              </button>
            ))}
          </div>

          <Field label="Instructions for the agent">
            <textarea className="textarea" rows={3} dir="auto" value={text} onChange={(e) => setText(e.target.value)} />
          </Field>

          <Field label="Add a link to send" hint="Optional — pick from this agent's saved links.">
            <select className="select" value={link} onChange={(e) => setLink(e.target.value)}>
              <option value="">No link</option>
              {base.links.map((l) => <option key={l.id} value={l.url}>{l.label}</option>)}
            </select>
          </Field>

          <div className="field__label" style={{ marginBottom: 8 }}>When</div>
          <div className="row" style={{ gap: 8, marginBottom: 18 }}>
            {BRIEF_TIMING.map((tm) => (
              <button key={tm.id} onClick={() => setTiming(tm.id)}
                style={{ height: 36, padding: "0 14px", borderRadius: 999, fontSize: 13, fontWeight: 600,
                  border: "1px solid " + (timing === tm.id ? "var(--color-secondary)" : "var(--border-2)"),
                  background: timing === tm.id ? "var(--color-secondary)" : "#fff", color: timing === tm.id ? "#fff" : "var(--fg-2)" }}>{tm.label}</button>
            ))}
          </div>

          <div className="row" style={{ gap: 8, background: "var(--color-primary-tint-soft)", border: "1px solid var(--color-primary-tint)", borderRadius: 12, padding: 12, marginBottom: 18, alignItems: "flex-start" }}>
            <Icon name="shield" size={16} style={{ color: "var(--color-secondary)", flexShrink: 0, marginTop: 1 }} />
            <span style={{ fontSize: 12.5, color: "var(--fg-2)", lineHeight: 1.5 }}>The agent writes the message in its own voice and sends the draft to your approval queue first.</span>
          </div>

          {err && <div className="row" style={{ gap: 10, background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 10, padding: "10px 12px", fontSize: 12.5 }}><Icon name="alert" size={15} />{err}</div>}
        </div>
        <div className="row" style={{ gap: 10, justifyContent: "flex-end", padding: "14px 22px", borderTop: "1px solid var(--border-1)", flexShrink: 0 }}>
          <Button variant="ghost" onClick={onClose} disabled={sending}>Cancel</Button>
          <Button variant="primary" icon="send" disabled={!text.trim() || sending} onClick={send}>{sending ? "Sending…" : `Send to ${agent?.name}`}</Button>
        </div>
        </>
      )}
    </Modal>
  );
}

/* ---- Dynamic Workflow panel (in the lead drawer) ---------------------- */
const WF_AGENT_ICON = {
  lead_discovery: "search", lead_qualification: "filter", research: "eye",
  offer_builder: "tag", content: "message", sales: "handshake", crm: "clipboard", learning: "trending",
};
const WF_STATUS_META = {
  completed: { tone: "green", dot: "#22C55E", label: "Done" },
  failed: { tone: "red", dot: "#B91C1C", label: "Failed" },
  running: { tone: "blue", dot: "#2563EB", label: "Running" },
  skipped: { tone: "neutral", dot: "#9CA3AF", label: "Skipped" },
  queued: { tone: "neutral", dot: "#D1D5DB", label: "Queued" },
};
function copyText(s) { try { navigator.clipboard?.writeText(s); } catch {} }
function fmtTime(iso) { try { return new Date(iso).toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit", second: "2-digit" }); } catch { return ""; } }

function WfStep({ reg, ar, busy, onRun, onRetry }) {
  const [open, setOpen] = useState(false);
  const status = ar?.status || "queued";
  const m = WF_STATUS_META[status] || WF_STATUS_META.queued;
  return (
    <div style={{ border: "1px solid var(--border-1)", borderRadius: 12, overflow: "hidden", background: "#fff" }}>
      <button className="between" onClick={() => ar && setOpen((v) => !v)} style={{ width: "100%", padding: "12px 14px", background: "none", textAlign: "start", cursor: ar ? "pointer" : "default", gap: 10 }}>
        <div className="row" style={{ gap: 10, minWidth: 0 }}>
          <span className="opp" style={{ width: 30, height: 30, borderRadius: 8, background: "var(--bg-2)", color: "var(--color-secondary)", flexShrink: 0 }}>
            <Icon name={WF_AGENT_ICON[reg.key] || "circle"} size={15} />
          </span>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 13 }}>{reg.name}</div>
            <div style={{ fontSize: 11.5, color: "var(--fg-4)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", maxWidth: 230 }}>{ar?.summary || reg.role}</div>
          </div>
        </div>
        <div className="row" style={{ gap: 8, flexShrink: 0 }}>
          {status === "running" || busy ? <span className="skel" style={{ width: 54, height: 20, borderRadius: 999 }} /> : <Badge tone={m.tone} dot={m.dot}>{m.label}</Badge>}
          {ar && <Icon name={open ? "chevronDown" : "chevronRight"} size={15} style={{ color: "var(--fg-disabled)" }} />}
        </div>
      </button>
      {open && ar && (
        <div style={{ padding: "0 14px 14px", borderTop: "1px solid var(--border-1)" }}>
          <div className="row wrap" style={{ gap: 12, fontSize: 11.5, color: "var(--fg-4)", margin: "10px 0" }}>
            {ar.startedAt && <span><Icon name="clock" size={12} style={{ verticalAlign: "-2px" }} /> {fmtTime(ar.startedAt)}</span>}
            {typeof ar.durationMs === "number" && <span>· {ar.durationMs} ms</span>}
            {typeof ar.confidence === "number" && ar.confidence > 0 && <span>· {Math.round(ar.confidence * 100)}% confidence</span>}
          </div>
          {ar.error && <div style={{ background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 8, padding: "8px 10px", fontSize: 12, marginBottom: 8 }}>{ar.error}</div>}
          {ar.logs?.length > 0 && (
            <ul style={{ margin: "0 0 8px", paddingInlineStart: 16, fontSize: 12, color: "var(--fg-3)", lineHeight: 1.5, display: "flex", flexDirection: "column", gap: 4 }}>
              {ar.logs.map((l, i) => <li key={i}>{l}</li>)}
            </ul>
          )}
          <div className="row" style={{ gap: 8 }}>
            <Button variant="subtle" size="sm" icon="refresh" onClick={() => onRun(reg.key)} disabled={busy}>Re-run</Button>
            {status === "failed" && <Button variant="ghost" size="sm" icon="play" onClick={() => onRetry(ar.id)} disabled={busy}>Retry</Button>}
          </div>
        </div>
      )}
    </div>
  );
}

function WfOutputCard({ icon, title, children, action }) {
  return (
    <Card>
      <div className="between" style={{ marginBottom: 10 }}>
        <div className="row" style={{ gap: 8 }}><Icon name={icon} size={16} style={{ color: "var(--color-secondary)" }} /><b style={{ fontSize: 13.5 }}>{title}</b></div>
        {action}
      </div>
      {children}
    </Card>
  );
}

function WaMessage({ label, text }) {
  return (
    <div style={{ border: "1px solid var(--border-1)", borderRadius: 10, padding: 12, background: "var(--bg-2)" }}>
      <div className="between" style={{ marginBottom: 6 }}>
        <span style={{ fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".04em", color: "var(--fg-4)" }}>{label}</span>
        <button className="iconbtn" style={{ width: 26, height: 26 }} title="Copy" onClick={() => copyText(text)}><Icon name="copy" size={13} /></button>
      </div>
      <div dir="auto" style={{ fontSize: 13, color: "var(--fg-1)", lineHeight: 1.6, whiteSpace: "pre-wrap" }}>{text}</div>
    </div>
  );
}

const WA_LABELS = [["first", "First message"], ["followUp", "Follow-up"], ["objection", "Objection reply"], ["closing", "Closing"], ["meeting", "Meeting booking"]];

function WorkflowPanel({ contact, agent }) {
  const data = useStore();
  const status = data.WORKFLOW_STATUS[contact.id];
  const registry = data.WORKFLOW_AGENTS || [];
  const [busy, setBusy] = useState(false);
  const [loadErr, setLoadErr] = useState(null);
  const [waLocal, setWaLocal] = useState(null);
  const [note, setNote] = useState("");
  const [fuAction, setFuAction] = useState("");
  const [fuWhen, setFuWhen] = useState("tomorrow");

  React.useEffect(() => {
    if (!status) Actions.loadWorkflowStatus(contact.id).catch((e) => setLoadErr(e.message));
  }, [contact.id]); // eslint-disable-line

  const run = status?.run;
  const agentRuns = status?.agentRuns || [];
  const byKey = {}; agentRuns.forEach((a) => { byKey[a.agentKey] = a; });
  const doneCount = agentRuns.filter((a) => a.status === "completed").length;
  const fr = run?.finalRecommendation;

  const runFull = async () => { setBusy(true); try { await Actions.runWorkflow(contact.id, "full"); setWaLocal(null); } catch (e) { setLoadErr(e.message); } finally { setBusy(false); } };
  const runOne = async (key) => { setBusy(true); try { await Actions.runAgent(contact.id, key); setWaLocal(null); } catch (e) { setLoadErr(e.message); } finally { setBusy(false); } };
  const retryOne = async (id) => { setBusy(true); try { await Actions.retryAgent(contact.id, id); } catch (e) { setLoadErr(e.message); } finally { setBusy(false); } };
  const genWa = async () => { setBusy(true); try { const r = await Actions.generateWhatsapp(contact.id); setWaLocal(r.messages); } catch (e) { setLoadErr(e.message); } finally { setBusy(false); } };
  const addNote = async () => { const t = note.trim(); if (!t) return; await Actions.addNote(contact.id, t); setNote(""); };
  const setStatus = (s) => Actions.updateLead(contact.id, { status: s }).catch((e) => setLoadErr(e.message));
  const setStage = (s) => Actions.updateLead(contact.id, { stage: s }).catch((e) => setLoadErr(e.message));
  const addFollowUp = async () => {
    const a = fuAction.trim(); if (!a) return;
    setBusy(true);
    try { await Actions.createFollowUp({ leadId: contact.id, when: fuWhen, action: a }); setFuAction(""); await Actions.loadWorkflowStatus(contact.id); }
    catch (e) { setLoadErr(e.message); } finally { setBusy(false); }
  };

  const research = status?.research;
  const offer = status?.offer;
  const crmRun = byKey.crm?.output;
  const waMessages = waLocal || byKey.content?.output?.messages;
  const followUps = status?.followUps || [];

  return (
    <div className="col" style={{ gap: 16 }}>
      {/* header / run control */}
      <div style={{ background: "var(--color-secondary)", color: "#fff", borderRadius: 16, padding: 18 }}>
        <div className="between" style={{ marginBottom: fr ? 12 : 0, alignItems: "flex-start" }}>
          <div>
            <div className="row" style={{ gap: 8 }}><Icon name="zap" size={18} /><b style={{ fontSize: 14 }}>Core Dynamic Workflow</b></div>
            <div style={{ fontSize: 12, opacity: 0.85, marginTop: 4 }}>
              {run ? <>{doneCount}/{registry.length} agents complete{run.status === "partial" ? " · some steps failed" : run.status === "completed" ? " · run complete" : run.status === "interrupted" ? " · interrupted by restart — re-run to continue" : ""}</> : "8 specialised agents · qualify → research → offer → content → sales → CRM → learning"}
            </div>
          </div>
          <Button variant="primary" size="sm" icon="zap" onClick={runFull} disabled={busy}>{busy ? "Running…" : run ? "Re-run all" : "Run workflow"}</Button>
        </div>
        {fr && (
          <div style={{ background: "rgba(255,255,255,0.12)", borderRadius: 12, padding: 12 }}>
            <div style={{ fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".04em", opacity: 0.8 }}>Final recommendation</div>
            <div style={{ fontSize: 13.5, lineHeight: 1.55, marginTop: 4 }}>{fr.summary}</div>
          </div>
        )}
      </div>

      {loadErr && <div style={{ background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 10, padding: "10px 12px", fontSize: 12.5 }}>{loadErr}</div>}

      {/* pipeline */}
      <div className="col" style={{ gap: 8 }}>
        {registry.map((reg) => (
          <WfStep key={reg.key} reg={reg} ar={byKey[reg.key]} busy={busy} onRun={runOne} onRetry={retryOne} />
        ))}
        {registry.length === 0 && <div className="skel" style={{ height: 56, borderRadius: 12 }} />}
      </div>

      {/* outputs */}
      {research && (
        <WfOutputCard icon="eye" title="Research report" action={<Badge tone={research.overall >= 70 ? "green" : research.overall >= 50 ? "blue" : "orange"}>{research.overall}/100</Badge>}>
          <div className="row" style={{ gap: 16, marginBottom: 12 }}>
            {[research.designQuality, research.speed, research.seo].filter(Boolean).map((s) => (
              <div key={s.label} style={{ flex: 1 }}>
                <div style={{ fontSize: 11, color: "var(--fg-4)", marginBottom: 4 }}>{s.label}</div>
                <ScoreBar value={s.score} />
              </div>
            ))}
          </div>
          {research.conversionProblems?.length > 0 && <>
            <div style={{ fontSize: 12, fontWeight: 700, color: "var(--color-orange)", margin: "4px 0 6px" }}>Conversion problems</div>
            <ul style={{ margin: 0, paddingInlineStart: 16, fontSize: 12.5, color: "var(--fg-2)", lineHeight: 1.5, display: "flex", flexDirection: "column", gap: 4 }}>
              {research.conversionProblems.map((p, i) => <li key={i}>{p}</li>)}
            </ul>
          </>}
          {research.opportunities?.length > 0 && <>
            <div style={{ fontSize: 12, fontWeight: 700, color: "var(--color-secondary)", margin: "10px 0 6px" }}>Opportunities</div>
            <ul style={{ margin: 0, paddingInlineStart: 16, fontSize: 12.5, color: "var(--fg-2)", lineHeight: 1.5, display: "flex", flexDirection: "column", gap: 4 }}>
              {research.opportunities.map((p, i) => <li key={i}>{p}</li>)}
            </ul>
          </>}
        </WfOutputCard>
      )}

      {offer && (
        <WfOutputCard icon="tag" title="Offer recommendation">
          <div className="row wrap" style={{ gap: 8, marginBottom: 10 }}>
            <Badge tone="lime">{offer.recommendedService?.name}</Badge>
            {offer.knowledgeCited?.title && <Badge tone="neutral">Anchor: {offer.knowledgeCited.title}</Badge>}
          </div>
          <p style={{ fontSize: 13, color: "var(--fg-2)", lineHeight: 1.6, marginBottom: 8 }}>{offer.reasoning}</p>
          <p style={{ fontSize: 12.5, color: "var(--fg-3)", lineHeight: 1.6 }}>{offer.valueProposition}</p>
          {offer.recommendedService?.url && <a href={offer.recommendedService.url} target="_blank" rel="noreferrer" className="row" style={{ gap: 6, marginTop: 10, fontSize: 12.5, fontWeight: 600, color: "var(--color-secondary)" }}><Icon name="external" size={14} />View service page</a>}
        </WfOutputCard>
      )}

      <WfOutputCard icon="message" title="WhatsApp outreach" action={<Button variant="subtle" size="sm" icon="refresh" onClick={genWa} disabled={busy}>{waMessages ? "Regenerate" : "Generate"}</Button>}>
        {waMessages ? (
          <div className="col" style={{ gap: 10 }}>
            {WA_LABELS.map(([k, label]) => waMessages[k] ? <WaMessage key={k} label={label} text={waMessages[k]} /> : null)}
          </div>
        ) : (
          <div style={{ fontSize: 12.5, color: "var(--fg-4)" }}>Run the workflow or click Generate to draft the 5 WhatsApp message types (Arabic for Gulf leads).</div>
        )}
      </WfOutputCard>

      <WfOutputCard icon="clipboard" title="CRM" action={crmOptKey(crmRun?.stage) ? <Badge tone="dark">{crmOptText(crmRun.stage)}</Badge> : (crmOptKey(contact.stage) ? <Badge tone="dark">{crmOptText(contact.stage)}</Badge> : null)}>
        <div className="row wrap" style={{ gap: 8, marginBottom: 12 }}>
          <Badge tone="neutral">{crmRun?.category || "—"}</Badge>
          <Badge tone="neutral">Owner: {crmRun?.owner || contact.agent}</Badge>
        </div>
        {/* manual CRM status + pipeline stage */}
        <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 10, marginBottom: 12 }}>
          <Field label="CRM status"><select className="select" style={{ height: 38 }} value={crmOptKey(contact.status)} onChange={(e) => setStatus(e.target.value)}>{(data.SETTINGS?.statuses || STATUS_ORDER).map((s) => { const k = crmOptKey(s); return <option key={k} value={k}>{crmOptText(s)}</option>; })}</select></Field>
          <Field label="Pipeline stage"><select className="select" style={{ height: 38 }} value={crmOptKey(contact.stage)} onChange={(e) => setStage(e.target.value)}><option value="">—</option>{(data.CRM_STAGES || []).map((s) => { const k = crmOptKey(s); return <option key={k} value={k}>{crmOptText(s)}</option>; })}</select></Field>
        </div>
        {/* follow-ups */}
        <div style={{ fontSize: 12, fontWeight: 700, color: "var(--fg-3)", margin: "4px 0 6px" }}>Follow-ups</div>
        {followUps.length > 0 && (
          <div className="col" style={{ gap: 6, marginBottom: 8 }}>
            {followUps.map((f) => (
              <div key={f.id} className="between" style={{ gap: 8, fontSize: 12.5 }}>
                <span className="row" style={{ gap: 6 }}><Icon name="clock" size={13} style={{ color: "var(--fg-4)" }} /> {f.action}</span>
                <Badge tone="neutral">{f.when}</Badge>
              </div>
            ))}
          </div>
        )}
        <div className="row" style={{ gap: 8, marginBottom: 12 }}>
          <input className="input" style={{ height: 38, flex: 1 }} placeholder="Schedule a follow-up…" value={fuAction} onChange={(e) => setFuAction(e.target.value)} onKeyDown={(e) => e.key === "Enter" && addFollowUp()} />
          <select className="select" style={{ height: 38, width: 120 }} value={fuWhen} onChange={(e) => setFuWhen(e.target.value)}>{["today", "tomorrow", "in 2 days", "in a week"].map((w) => <option key={w} value={w}>{w}</option>)}</select>
          <Button variant="subtle" size="sm" icon="calendar" onClick={addFollowUp} disabled={!fuAction.trim() || busy}>Add</Button>
        </div>
        {/* notes */}
        <div style={{ fontSize: 12, fontWeight: 700, color: "var(--fg-3)", margin: "4px 0 6px" }}>Notes</div>
        {(contact.notes || []).length > 0 && (
          <div className="col" style={{ gap: 6, marginBottom: 8 }}>
            {contact.notes.map((n) => (
              <div key={n.id} style={{ fontSize: 12.5, color: "var(--fg-2)", background: "var(--bg-2)", borderRadius: 8, padding: "8px 10px" }}>
                {n.text}<div style={{ fontSize: 11, color: "var(--fg-4)", marginTop: 2 }}>{n.by} · {fmtTime(n.at)}</div>
              </div>
            ))}
          </div>
        )}
        <div className="row" style={{ gap: 8 }}>
          <input className="input" style={{ height: 38, flex: 1 }} placeholder="Add a note…" value={note} onChange={(e) => setNote(e.target.value)} onKeyDown={(e) => e.key === "Enter" && addNote()} />
          <Button variant="subtle" size="sm" icon="plus" onClick={addNote} disabled={!note.trim()}>Save</Button>
        </div>
      </WfOutputCard>
    </div>
  );
}

/* ---- Add lead + Discover leads modals --------------------------------- */
const COUNTRIES = [["SA", "Saudi Arabia"], ["AE", "UAE"], ["EG", "Egypt"], ["KW", "Kuwait"], ["QA", "Qatar"], ["BH", "Bahrain"], ["OM", "Oman"], ["JO", "Jordan"]];
const PLATFORMS_PICK = ["Shopify", "Salla", "Zid", "WooCommerce", "WordPress", "Custom", "None"];

const VALUE_BANDS = ["S", "M", "L", "XL"];
const PRIORITIES = ["urgent", "high", "medium", "low", "cold"];

function AddLeadModal({ onClose, onCreated, lead }) {
  const editing = Boolean(lead);
  const [f, setF] = useState(() => editing
    ? { name: lead.name || "", person: lead.person || "", phone: lead.phone || "", country: lead.country || "SA", city: lead.city || "", platform: lead.platform || "Unknown", value: lead.value || "M", priority: lead.priority || "low", website: lead.website || "", email: lead.email || "", gmaps: lead.gmaps || lead.googleMapsUrl || "" }
    : { name: "", person: "", phone: "", country: "SA", city: "", platform: "Salla", value: "M", priority: "low", website: "", email: "", gmaps: "" });
  const [busy, setBusy] = useState(false);
  const set = (k, v) => setF((s) => ({ ...s, [k]: v }));
  const save = async () => {
    if (!f.name.trim() && !f.phone.trim()) return;
    setBusy(true);
    try {
      const c = editing ? await Actions.updateLead(lead.id, f) : await Actions.createLead(f);
      onClose();
      onCreated && onCreated(c);
    } catch (e) { alert("Couldn't save lead: " + e.message); setBusy(false); }
  };
  return (
    <Modal onClose={onClose} style={{ width: 520, display: "flex", flexDirection: "column", maxHeight: "90vh", overflow: "hidden", padding: 0 }}>
      <div className="between" style={{ padding: "18px 22px", borderBottom: "1px solid var(--border-1)", flexShrink: 0 }}>
        <div><div style={{ fontWeight: 800, fontSize: 16 }}>{editing ? "Edit lead" : "Add a lead"}</div><div style={{ fontSize: 12, color: "var(--fg-4)" }}>{editing ? "Update this lead's details" : "Then run the Dynamic Workflow on it"}</div></div>
        <button className="iconbtn" onClick={onClose}><Icon name="x" size={20} /></button>
      </div>
      <div style={{ padding: 22, overflowY: "auto", flex: 1 }}>
        <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <Field label="Store name"><input className="input" value={f.name} onChange={(e) => set("name", e.target.value)} placeholder="Store or company name" /></Field>
          <Field label="Contact person"><input className="input" value={f.person} onChange={(e) => set("person", e.target.value)} placeholder="Contact person name" /></Field>
          <Field label="Phone"><input className="input" dir="ltr" value={f.phone} onChange={(e) => set("phone", e.target.value)} placeholder="+966 5x xxx xxxx" /></Field>
          <Field label="City"><input className="input" value={f.city} onChange={(e) => set("city", e.target.value)} placeholder="Riyadh" /></Field>
          <Field label="Country"><select className="select" value={f.country} onChange={(e) => set("country", e.target.value)}>{COUNTRIES.map(([k, n]) => <option key={k} value={k}>{n}</option>)}</select></Field>
          <Field label="Platform"><select className="select" value={f.platform} onChange={(e) => set("platform", e.target.value)}>{PLATFORMS_PICK.map((p) => <option key={p} value={p}>{p}</option>)}</select></Field>
          <Field label="Opportunity value"><select className="select" value={f.value} onChange={(e) => set("value", e.target.value)}>{VALUE_BANDS.map((v) => <option key={v} value={v}>{v}</option>)}</select></Field>
          <Field label="Priority"><select className="select" value={f.priority} onChange={(e) => set("priority", e.target.value)}>{PRIORITIES.map((p) => <option key={p} value={p}>{p}</option>)}</select></Field>
        </div>
        <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12, marginTop: 12 }}>
          <Field label="Website" hint="Enables Website Intelligence"><input className="input" dir="ltr" value={f.website} onChange={(e) => set("website", e.target.value)} placeholder="reem.salla.sa" /></Field>
          <Field label="Email"><input className="input" dir="ltr" value={f.email} onChange={(e) => set("email", e.target.value)} placeholder="owner@store.com" /></Field>
          <Field label="Google Maps URL" hint="Enables Maps Intelligence"><input className="input" dir="ltr" value={f.gmaps} onChange={(e) => set("gmaps", e.target.value)} placeholder="https://maps.google.com/…" /></Field>
        </div>
      </div>
      <div className="row" style={{ gap: 10, justifyContent: "flex-end", padding: "14px 22px", borderTop: "1px solid var(--border-1)", flexShrink: 0 }}>
        <Button variant="ghost" onClick={onClose}>Cancel</Button>
        <Button variant="primary" icon={editing ? "check" : "plus"} disabled={busy || (!f.name.trim() && !f.phone.trim())} onClick={save}>{busy ? "Saving…" : editing ? "Save changes" : "Add lead"}</Button>
      </div>
    </Modal>
  );
}

function DiscoverLeadsModal({ onClose }) {
  const [platforms, setPlatforms] = useState(["Salla", "Zid"]);
  const [country, setCountry] = useState("SA");
  const [count, setCount] = useState(6);
  const [busy, setBusy] = useState(false);
  const [result, setResult] = useState(null);
  const toggle = (p) => setPlatforms((s) => (s.includes(p) ? s.filter((x) => x !== p) : [...s, p]));
  const run = async () => {
    setBusy(true);
    try { const r = await Actions.discoverLeads({ platforms, country, count: Number(count) }); setResult(r); }
    catch (e) { alert("Discovery failed: " + e.message); }
    finally { setBusy(false); }
  };
  return (
    <Modal onClose={onClose} style={{ width: 560 }}>
      <div className="between" style={{ padding: "18px 22px", borderBottom: "1px solid var(--border-1)" }}>
        <div className="row" style={{ gap: 12 }}>
          <span className="opp" style={{ width: 38, height: 38, borderRadius: 10, background: "var(--color-primary-tint)", color: "var(--color-secondary)" }}><Icon name="search" size={19} /></span>
          <div><div className="row" style={{ gap: 8 }}><span style={{ fontWeight: 800, fontSize: 16 }}>Discover leads</span><Badge tone="orange">Demo · Coming soon</Badge></div><div style={{ fontSize: 12, color: "var(--fg-4)" }}>Generates realistic <b>sample</b> leads to try the workflow</div></div>
        </div>
        <button className="iconbtn" onClick={onClose}><Icon name="x" size={20} /></button>
      </div>
      <div style={{ padding: 22 }}>
        {result ? (
          <div style={{ textAlign: "center", padding: "10px 0 4px" }}>
            <span className="opp" style={{ width: 56, height: 56, borderRadius: 16, background: "var(--color-primary)", color: "var(--color-secondary)", margin: "0 auto 14px" }}><Icon name="checkcircle" size={28} /></span>
            <div style={{ fontWeight: 700, fontSize: 15 }}>Generated {result.count} sample leads</div>
            <p className="muted" style={{ fontSize: 13, maxWidth: 380, margin: "8px auto 16px" }}>They're added to your leads with status “New”. Open any one and run the Dynamic Workflow to qualify, research and build an offer.</p>
            <Button variant="primary" onClick={onClose}>View leads</Button>
          </div>
        ) : (
          <>
            <div className="row" style={{ gap: 8, marginBottom: 14, background: "#FFF7ED", border: "1px solid #FED7AA", borderRadius: 10, padding: "10px 12px", fontSize: 12, color: "var(--fg-2)" }}><Icon name="info" size={14} style={{ color: "#EA580C", flexShrink: 0 }} /><span><b>Demo feature — coming soon.</b> This generates <b>fabricated sample leads</b> from a built-in generator (not live prospects) so you can try the Dynamic Workflow. Real store-directory discovery is planned. For production, <b>Import</b> your real leads or add them manually.</span></div>
            <div className="field__label" style={{ marginBottom: 8 }}>Platforms</div>
            <div className="row wrap" style={{ gap: 8, marginBottom: 16 }}>
              {["Shopify", "Salla", "Zid"].map((p) => (
                <button key={p} onClick={() => toggle(p)}
                  style={{ height: 36, padding: "0 16px", borderRadius: 999, fontSize: 13, fontWeight: 600,
                    border: "1px solid " + (platforms.includes(p) ? "var(--color-secondary)" : "var(--border-2)"),
                    background: platforms.includes(p) ? "var(--color-secondary)" : "#fff", color: platforms.includes(p) ? "#fff" : "var(--fg-2)" }}>
                  {platforms.includes(p) && <Icon name="check" size={14} style={{ verticalAlign: "-2px", marginInlineEnd: 4 }} />}{p}
                </button>
              ))}
            </div>
            <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 12 }}>
              <Field label="Country"><select className="select" value={country} onChange={(e) => setCountry(e.target.value)}>{COUNTRIES.map(([k, n]) => <option key={k} value={k}>{n}</option>)}</select></Field>
              <Field label="How many"><input className="input" type="number" min="1" max="24" value={count} onChange={(e) => setCount(e.target.value)} /></Field>
            </div>
            <div className="row" style={{ gap: 10, justifyContent: "flex-end", marginTop: 8 }}>
              <Button variant="ghost" onClick={onClose}>Cancel</Button>
              <Button variant="primary" icon="search" disabled={busy || !platforms.length} onClick={run}>{busy ? "Discovering…" : "Discover"}</Button>
            </div>
          </>
        )}
      </div>
    </Modal>
  );
}

window.ContactsScreen = ContactsScreen;
window.ContactDrawer = ContactDrawer;
window.DrawerHead = DrawerHead;
window.RetargetOverlay = RetargetOverlay;
window.BriefAgentModal = BriefAgentModal;
window.WorkflowPanel = WorkflowPanel;
window.AddLeadModal = AddLeadModal;
window.DiscoverLeadsModal = DiscoverLeadsModal;
