// screens-conversations.jsx — WhatsApp-style inbox wired to the backend.
// The composer runs the live Dynamic Workflow (regenerate/approve/reject) and
// can reveal the agent trace. Inbox + approvals come from the live store.
const { useState, useEffect } = React;
const VALUE_PCT = { S: 25, M: 55, L: 80, XL: 95 };

const WA_STATUS_LABEL = { queued: "Queued", sent: "Sent", delivered: "Delivered", read: "Read", failed: "Failed" };

// 🎤 Voice note: real audio player + transcript + View/Copy/Re-transcribe/Download.
function VoiceNote({ m, convId, onChanged, you }) {
  const [busy, setBusy] = useState(false);
  const [open, setOpen] = useState(true);
  const [copied, setCopied] = useState(false);
  const [tx, setTx] = useState({ transcript: m.transcript, error: m.transcriptError, confidence: m.transcriptConfidence, provider: m.transcriptProvider });
  const mediaUrl = m.mediaFile ? `/api/whatsapp/media/${m.mediaFile}` : null;
  const d = Math.round(m.durationSec || 0);
  const dur = d ? `${Math.floor(d / 60)}:${String(d % 60).padStart(2, "0")}` : null;
  const tcolor = you ? "rgba(255,255,255,.85)" : "var(--fg-2)";
  const retranscribe = () => {
    if (!convId) return; setBusy(true);
    API.conversations.retranscribe(convId, m.id)
      .then((r) => { setTx({ transcript: r.transcript, error: r.ok ? null : (r.error || "failed"), confidence: r.confidence, provider: r.provider }); onChanged && onChanged(); })
      .catch((e) => setTx((p) => ({ ...p, error: (e.message || "failed").slice(0, 80) })))
      .finally(() => setBusy(false));
  };
  const copy = () => { if (tx.transcript && navigator.clipboard) { navigator.clipboard.writeText(tx.transcript); setCopied(true); setTimeout(() => setCopied(false), 1500); } };
  return (
    <div className="col" style={{ gap: 8, minWidth: 220 }}>
      <div className="row" style={{ gap: 8 }}>
        <Icon name="mic" size={16} style={{ color: you ? "#fff" : "var(--color-secondary)" }} />
        <b style={{ fontSize: 12.5, color: tcolor }}>Voice note{dur ? ` · ${dur}` : ""}</b>
        {tx.provider && tx.transcript && <span style={{ fontSize: 10, color: tcolor, opacity: 0.7 }}>via {tx.provider}</span>}
      </div>
      {mediaUrl && <audio controls preload="none" style={{ width: "100%", height: 34 }} src={mediaUrl} />}
      {tx.transcript ? (
        <>
          {open && <div style={{ fontSize: 13.5, lineHeight: 1.5, color: you ? "#fff" : "var(--fg-1)", background: you ? "rgba(255,255,255,.12)" : "var(--bg-2)", borderRadius: 10, padding: "8px 10px" }} dir="auto">{tx.transcript}{Number.isFinite(tx.confidence) ? <span style={{ display: "block", fontSize: 10.5, opacity: 0.7, marginTop: 4 }}>Transcript · {Math.round(tx.confidence * 100)}% confidence</span> : null}</div>}
          <div className="row wrap" style={{ gap: 6 }}>
            <button className="btn btn--subtle btn--sm" onClick={() => setOpen((v) => !v)}><Icon name="message" size={13} />{open ? "Hide transcript" : "View transcript"}</button>
            <button className="btn btn--subtle btn--sm" onClick={copy}><Icon name="copy" size={13} />{copied ? "Copied" : "Copy"}</button>
            <button className="btn btn--subtle btn--sm" disabled={busy} onClick={retranscribe}><Icon name="refresh" size={13} />{busy ? "…" : "Re-transcribe"}</button>
            {mediaUrl && <a className="btn btn--subtle btn--sm" href={mediaUrl} download><Icon name="download" size={13} />Download</a>}
          </div>
        </>
      ) : (
        <div className="col" style={{ gap: 6 }}>
          <div className="row" style={{ gap: 6, fontSize: 12.5, color: you ? "#FECACA" : "var(--color-danger)" }}><Icon name="alert" size={13} />Couldn't transcribe{tx.error ? `: ${tx.error}` : ""}.</div>
          <div className="row wrap" style={{ gap: 6 }}>
            <button className="btn btn--subtle btn--sm" disabled={busy} onClick={retranscribe}><Icon name="refresh" size={13} />{busy ? "Transcribing…" : "Retry transcription"}</button>
            {mediaUrl && <a className="btn btn--subtle btn--sm" href={mediaUrl} download><Icon name="download" size={13} />Download audio</a>}
          </div>
        </div>
      )}
    </div>
  );
}

function Bubble({ m, convId, onChanged }) {
  const mine = m.from === "agent" || m.from === "you";
  const you = m.from === "you";
  const hasWa = mine && (m.waStatus || m.waMode);
  const failed = m.waStatus === "failed";
  const metaColor = you ? "rgba(255,255,255,.7)" : "var(--fg-4)";
  return (
    <div style={{ display: "flex", justifyContent: mine ? "flex-end" : "flex-start", marginBottom: 10 }}>
      <div style={{ maxWidth: "74%", background: mine ? (you ? "var(--color-secondary)" : "var(--color-primary-tint)") : "#fff",
        color: you ? "#fff" : "var(--fg-1)",
        border: "1px solid " + (failed ? "var(--color-danger)" : mine ? "transparent" : "var(--border-1)"),
        borderRadius: 16, borderBottomRightRadius: mine ? 4 : 16, borderBottomLeftRadius: mine ? 16 : 4, padding: "10px 14px", boxShadow: "var(--shadow-xs)" }}>
        {you && <div style={{ fontSize: 10, fontWeight: 700, opacity: 0.8, marginBottom: 2 }}>You</div>}
        {m.type === "voice"
          ? <VoiceNote m={m} convId={convId} onChanged={onChanged} you={you} />
          : <p style={{ fontSize: 14, lineHeight: 1.55 }} dir="auto">{m.text}</p>}
        <div className="row" style={{ gap: 5, justifyContent: "flex-end", marginTop: 4, flexWrap: "wrap" }}>
          <span style={{ fontSize: 10, color: metaColor }}>{m.at}</span>
          {hasWa && m.waMode === "simulation" && <span style={{ fontSize: 9, fontWeight: 700, color: metaColor, border: "1px solid " + metaColor, borderRadius: 4, padding: "0 4px" }}>SIM</span>}
          {hasWa && !failed && <span style={{ fontSize: 10, color: m.waStatus === "read" ? (you ? "#fff" : "var(--color-blue)") : metaColor }}>{WA_STATUS_LABEL[m.waStatus] || "Sent"}</span>}
          {mine && !hasWa && <Icon name="check2" size={14} style={{ color: you ? "#fff" : "var(--color-blue)" }} />}
        </div>
        {failed && <div style={{ fontSize: 10.5, color: you ? "#FECACA" : "var(--color-danger)", marginTop: 3, fontWeight: 600 }}><Icon name="alert" size={11} style={{ verticalAlign: "-1px" }} /> Failed to send{m.sendError ? `: ${m.sendError}` : ""}</div>}
      </div>
    </div>
  );
}

function TracePanel({ trace, live }) {
  if (!trace || !trace.length) return null;
  const tone = { done: "var(--color-success)", passed: "var(--color-success)", branch: "var(--color-secondary)",
    revised: "var(--color-orange)", fallback: "var(--color-orange)", offline: "var(--fg-4)", skipped: "var(--fg-4)", flagged: "var(--color-danger)" };
  return (
    <div style={{ marginTop: 10, background: "#fff", border: "1px solid var(--border-1)", borderRadius: 12, padding: 12 }}>
      <div className="row" style={{ gap: 6, marginBottom: 8 }}>
        <Icon name="bot" size={14} style={{ color: "var(--color-secondary)" }} />
        <b style={{ fontSize: 12 }}>Dynamic Workflow</b>
        <Badge tone={live ? "green" : "neutral"}>{live ? "Live Claude" : "Template mode"}</Badge>
      </div>
      <div className="col" style={{ gap: 6 }}>
        {trace.map((s, i) => (
          <div key={i} className="row" style={{ gap: 8, alignItems: "flex-start" }}>
            <span className="sdot" style={{ background: tone[s.status] || "var(--fg-4)", marginTop: 6 }} />
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 12, fontWeight: 700 }}>{s.name} <span style={{ fontWeight: 500, color: "var(--fg-4)" }}>· {s.status}</span></div>
              <div style={{ fontSize: 11.5, color: "var(--fg-3)" }}>{s.detail}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function ComposerError({ msg, onDismiss }) {
  if (!msg) return null;
  return (
    <div className="row" style={{ gap: 8, background: "var(--color-danger-soft)", color: "var(--color-danger)", borderRadius: 10, padding: "8px 12px", marginBottom: 10, fontSize: 12.5, lineHeight: 1.5 }}>
      <Icon name="alert" size={15} style={{ flexShrink: 0, marginTop: 1 }} />
      <span style={{ flex: 1 }}>{msg}</span>
      {onDismiss && <button className="iconbtn" style={{ width: 22, height: 22, color: "var(--color-danger)" }} onClick={onDismiss}><Icon name="x" size={13} /></button>}
    </div>
  );
}

function ApprovalComposer({ conv, agent, onChanged }) {
  const draft = conv.pendingDraft;
  const [text, setText] = useState(draft ? draft.text : "");
  const [editing, setEditing] = useState(false);
  const [busy, setBusy] = useState(null); // 'regen' | 'approve' | 'reject'
  const [showTrace, setShowTrace] = useState(false);
  const [err, setErr] = useState(null);
  const [teach, setTeach] = useState(false);
  const [fb, setFb] = useState("");
  const [taught, setTaught] = useState(null);

  useEffect(() => { setText(draft ? draft.text : ""); setEditing(false); setErr(null); setTeach(false); setFb(""); setTaught(null); }, [conv.id, draft && draft.id]);

  if (!draft) return null;
  const conf = Math.round((draft.confidence || 0) * 100);
  const isAr = /[؀-ۿ]/.test(text);

  const regen = async () => { setBusy("regen"); setErr(null); try { const r = await Actions.regenerate(conv.id); onChanged(r.conversation); const nd = (r.conversation && r.conversation.pendingDraft) || r.draft; if (nd) { setText(nd.text || ""); setEditing(false); } setShowTrace(true); } catch (e) { setErr("Couldn't regenerate the draft: " + e.message); } finally { setBusy(null); } };
  const approve = async () => { setBusy("approve"); setErr(null); try { const r = await Actions.approve(conv.id, text); onChanged(r.conversation); } catch (e) { setErr("Couldn't send the reply: " + e.message); } finally { setBusy(null); } };
  const reject = async () => { setBusy("reject"); setErr(null); try { const r = await Actions.reject(conv.id); onChanged(r.conversation); } catch (e) { setErr("Couldn't reject the draft: " + e.message); } finally { setBusy(null); } };
  const saveLesson = async () => { const t = fb.trim(); if (!t) return; setBusy("teach"); setErr(null); try { const r = await API.conversations.feedback(conv.id, t); setTaught(r); setFb(""); setTeach(false); } catch (e) { setErr("Couldn't save the lesson: " + e.message); } finally { setBusy(null); } };

  return (
    <div style={{ borderTop: "1px solid var(--border-1)", background: "#fff", padding: 16 }}>
      <div style={{ background: "var(--color-primary-tint-soft)", border: "1px solid var(--color-primary-tint)", borderRadius: 14, padding: 14 }}>
        <div className="between" style={{ marginBottom: 10 }}>
          <div className="row" style={{ gap: 8 }}>
            <Icon name="sparkles" size={16} style={{ color: "var(--color-secondary)" }} />
            <b style={{ fontSize: 13, color: "var(--color-secondary)" }}>{agent} drafted a reply</b>
            <Badge tone={conf >= 85 ? "green" : conf >= 70 ? "lime" : "orange"}>{conf}% confidence</Badge>
          </div>
          <button className="btn btn--subtle btn--sm" onClick={() => setShowTrace((v) => !v)}>
            <Icon name="bot" size={13} />{showTrace ? "Hide" : "Why"}
          </button>
        </div>
        {editing
          ? <textarea className="textarea" dir={isAr ? "rtl" : "ltr"} rows={4} value={text} onChange={(e) => setText(e.target.value)} style={{ marginBottom: 12 }} />
          : <p dir="auto" style={{ fontSize: 14, lineHeight: 1.6, color: "var(--fg-1)", marginBottom: 12, whiteSpace: "pre-wrap" }}>{text}</p>}
        <ComposerError msg={err} onDismiss={() => setErr(null)} />
        {/* wrap so the primary "Approve & send" action never clips when the
            lead-details rail narrows the thread column on desktop (~544px). */}
        <div className="between" style={{ flexWrap: "wrap", gap: 8 }}>
          <div className="row" style={{ gap: 6, flexWrap: "wrap" }}>
            {editing
              ? <button className="btn btn--subtle btn--sm" onClick={() => setEditing(false)}>Done editing</button>
              : <button className="btn btn--subtle btn--sm" onClick={() => setEditing(true)}><Icon name="edit" size={14} />Edit</button>}
            <button className="btn btn--subtle btn--sm" onClick={regen} disabled={!!busy}>
              <Icon name="refresh" size={14} />{busy === "regen" ? "Thinking…" : "Regenerate"}
            </button>
            <button className="btn btn--subtle btn--sm" onClick={() => { setTeach((v) => !v); setTaught(null); }} title="Teach the agent — the lesson applies to every future reply"><Icon name="sparkles" size={14} />Teach</button>
          </div>
          <div className="row" style={{ gap: 6, flexShrink: 0 }}>
            <button className="btn btn--ghost btn--sm" onClick={reject} disabled={!!busy}><Icon name="x" size={14} />Reject</button>
            <Button variant="primary" size="sm" icon="send" onClick={approve} disabled={!!busy || !text.trim()}>
              {busy === "approve" ? "Sending…" : "Approve & send"}
            </Button>
          </div>
        </div>
        {teach && (
          <div className="col" style={{ gap: 8, marginTop: 12, background: "var(--bg-2)", borderRadius: 12, padding: 12 }}>
            <div style={{ fontSize: 12, fontWeight: 700, color: "var(--fg-2)" }}>Teach {agent} — applies to every future reply</div>
            <textarea className="textarea" rows={2} dir="auto" placeholder="e.g. هذا الرد رسمي زيادة، خليه أقصر · don't lead with price" value={fb} onChange={(e) => setFb(e.target.value)} />
            <div className="row" style={{ gap: 6 }}>
              <Button variant="dark" size="sm" icon="check" disabled={!fb.trim() || busy === "teach"} onClick={saveLesson}>{busy === "teach" ? "Saving…" : "Save lesson"}</Button>
              <button className="btn btn--ghost btn--sm" onClick={() => { setTeach(false); setFb(""); }}>Cancel</button>
            </div>
          </div>
        )}
        {taught && <div className="row" style={{ gap: 6, marginTop: 8, fontSize: 12, color: "#15803D" }}><Icon name="checkcircle" size={14} />Lesson saved ({taught.category}) — {agent} now has {taught.totalCorrections} correction{taught.totalCorrections === 1 ? "" : "s"} applied to future replies.</div>}
        <div style={{ marginTop: 8, fontSize: 11, color: "var(--fg-4)" }}>{draft.reviewerNote || "Self-checked"}</div>
        {showTrace && <TracePanel trace={draft.trace} live={draft.live} />}
      </div>
    </div>
  );
}

function ManualComposer({ conv, placeholder, as, onChanged }) {
  const [text, setText] = useState("");
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);
  const send = async () => {
    if (!text.trim() || busy) return;
    setBusy(true); setErr(null);
    try { const r = await Actions.sendManual(conv.id, text, as); setText(""); onChanged(r.conversation); }
    catch (e) { setErr("Couldn't send the message: " + e.message); }
    finally { setBusy(false); }
  };
  return (
    <div style={{ padding: 16 }}>
      <ComposerError msg={err} onDismiss={() => setErr(null)} />
      <div className="row" style={{ gap: 10, background: "var(--bg-2)", borderRadius: 12, padding: "10px 14px" }}>
        <Icon name="paperclip" size={18} style={{ color: "var(--fg-4)" }} />
        <input className="input" style={{ border: "none", background: "transparent", height: 28, padding: 0 }}
          placeholder={placeholder} value={text} dir="auto"
          onChange={(e) => setText(e.target.value)} onKeyDown={(e) => e.key === "Enter" && send()} />
        <button className="iconbtn" style={{ width: 32, height: 32, color: "var(--color-secondary)" }} onClick={send} disabled={busy}><Icon name="send" size={18} /></button>
      </div>
    </div>
  );
}

function InboxItem({ t, active, onClick }) {
  return (
    <button onClick={onClick} style={{ display: "flex", gap: 12, width: "100%", textAlign: "start", padding: "12px 16px",
      borderBottom: "1px solid var(--border-1)", background: active ? "var(--color-primary-tint-soft)" : "transparent", position: "relative" }}>
      {active && <span style={{ position: "absolute", insetInlineStart: 0, top: 8, bottom: 8, width: 3, background: "var(--color-secondary)", borderRadius: 999 }} />}
      <Avatar name={t.person} color={t.color} />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div className="between"><b style={{ fontSize: 13.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{t.name}</b><span style={{ fontSize: 11, color: "var(--fg-4)", flexShrink: 0 }}>{t.at}</span></div>
        <div className="row" style={{ gap: 6, marginTop: 3 }}>
          <span dir="auto" style={{ fontSize: 12.5, color: t.unread ? "var(--fg-1)" : "var(--fg-4)", fontWeight: t.unread ? 600 : 400, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", flex: 1 }}>{t.last}</span>
        </div>
        <div className="row" style={{ gap: 5, marginTop: 6 }}>
          {t.needsApproval && <Badge tone="lime">Approve</Badge>}
          {t.hot && <span style={{ display: "inline-flex", alignItems: "center", gap: 2, color: "var(--color-orange)", fontSize: 11, fontWeight: 700 }}><Icon name="flame" size={12} />Hot</span>}
        </div>
      </div>
      {t.unread && <span className="sdot" style={{ background: "var(--color-secondary)", marginTop: 6 }} />}
    </button>
  );
}

function ConversationsScreen() {
  const { openContact } = useApp();
  useStore(); // re-render on store changes (approvals, inbox)
  const inbox = DATA.CONVERSATIONS || [];
  const [activeId, setActiveId] = useState(inbox[0] ? inbox[0].id : null);
  const [detail, setDetail] = useState(null);
  const [loading, setLoading] = useState(false);
  // details rail starts open on desktop, closed on narrow screens (it overlays as a drawer there)
  const [railOpen, setRailOpen] = useState(() => (typeof window !== "undefined" ? window.innerWidth > 900 : true));
  // mobile single-pane view: "inbox" ↔ "thread" (ignored on desktop via CSS)
  const [mobileView, setMobileView] = useState("inbox");
  const [filter, setFilter] = useState("all");
  const [actionErr, setActionErr] = useState(null);

  const list = inbox.filter((t) => (filter === "all" ? true : filter === "approve" ? t.needsApproval : t.hot));

  // load detail when the active conversation changes
  useEffect(() => {
    if (!activeId) return;
    let alive = true;
    setLoading(true);
    API.conversations.get(activeId).then((d) => { if (alive) { setDetail(d); setLoading(false); } }).catch(() => alive && setLoading(false));
    return () => { alive = false; };
  }, [activeId]);

  // LIVE UPDATE: poll the inbox + active thread every 4s while the tab is visible
  // (pauses when hidden, refetches on focus). Inbox only re-renders when it
  // actually changed; the active thread updates only when its content changed —
  // so a new inbound WhatsApp reply + its AI draft appear with no refresh, no
  // flicker, and no scroll jump.
  useEffect(() => {
    const sig = (d) => (d ? `${(d.messages || []).length}|${d.pendingDraft?.id || ""}|${(d.pendingDraft?.text || "").length}|${d.at}|${d.taken ? 1 : 0}` : "");
    const tick = async () => {
      if (typeof document !== "undefined" && document.hidden) return;
      try { await Actions.refreshConversations(); } catch {}
      if (activeId) {
        try { const d = await API.conversations.get(activeId); setDetail((prev) => (sig(prev) === sig(d) ? prev : d)); } catch {}
      }
    };
    const id = setInterval(tick, 4000);
    const onVis = () => { if (!document.hidden) tick(); };
    document.addEventListener("visibilitychange", onVis);
    return () => { clearInterval(id); document.removeEventListener("visibilitychange", onVis); };
  }, [activeId]);

  if (!activeId || !inbox.length) {
    return (
      <div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
        <div style={{ padding: "12px 16px 0" }}><FallbackBanner compact /></div>
        <div style={{ flex: 1, display: "grid", placeItems: "center", color: "var(--fg-4)" }}>No conversations yet.</div>
      </div>
    );
  }

  const summary = inbox.find((t) => t.id === activeId) || inbox[0];
  // Always resolve the agent name from agentId (source of truth) so a renamed
  // agent never shows a stale string in the byline / buttons / paused notice.
  const agentName = agentNameOf(summary);
  const contact = detail ? detail.contact : DATA.CONTACTS.find((c) => c.id === summary.contactId);
  const taken = detail ? Boolean(detail.taken) : false;
  const onChanged = (conv) => setDetail(conv);
  const toggleTaken = async () => {
    setActionErr(null);
    try { const r = await Actions.takeover(activeId, !taken); setDetail(r.conversation); }
    catch (e) { setActionErr("Couldn't change who's handling this thread: " + e.message); }
  };

  return (
    <div className={"conv" + (railOpen ? " conv--rail" : "")} data-mv={mobileView} style={{ transition: "grid-template-columns var(--motion-base) var(--ease-standard)" }}>
      {/* inbox list */}
      <div className="conv__inbox" style={{ borderInlineEnd: "1px solid var(--border-1)", background: "#fff", display: "flex", flexDirection: "column", overflow: "hidden" }}>
        <div style={{ padding: 16, borderBottom: "1px solid var(--border-1)" }}>
          <Seg value={filter} onChange={setFilter} options={[{ value: "all", label: "All" }, { value: "approve", label: "Needs approval" }, { value: "hot", label: "Hot" }]} />
        </div>
        <div style={{ overflowY: "auto", flex: 1 }}>
          {list.map((t) => <InboxItem key={t.id} t={t} active={t.id === activeId} onClick={() => { setActiveId(t.id); setMobileView("thread"); }} />)}
          {!list.length && <div style={{ padding: 24, textAlign: "center", color: "var(--fg-4)", fontSize: 13 }}>Nothing here.</div>}
        </div>
      </div>

      {/* thread */}
      <div className="conv__thread" style={{ display: "flex", flexDirection: "column", overflow: "hidden", background: "var(--bg-2)" }}>
        <div style={{ flexShrink: 0, padding: "12px 16px 0" }}><FallbackBanner compact /></div>
        <div className="between" style={{ padding: "12px 20px", borderBottom: "1px solid var(--border-1)", background: "#fff" }}>
          <div className="row" style={{ gap: 12 }}>
            <button className="conv__back iconbtn" title="Back to inbox" onClick={() => setMobileView("inbox")}><Icon name="chevronLeft" size={18} /></button>
            <Avatar name={summary.person} color={summary.color} />
            <div>
              <div style={{ fontWeight: 700, fontSize: 14 }}>{summary.name}</div>
              <div className="row" style={{ gap: 6, fontSize: 12, color: "var(--fg-4)" }}>
                {taken ? <><Icon name="user" size={12} style={{ color: "var(--color-secondary)" }} /><b style={{ color: "var(--color-secondary)" }}>You're handling this</b></> : <><Icon name="bot" size={12} />{agentName}</>}
                <span>·</span><StatusPill status={summary.status} />
              </div>
            </div>
          </div>
          <div className="row" style={{ gap: 6 }}>
            <button className={"btn btn--sm " + (taken ? "btn--primary" : "btn--subtle")} onClick={toggleTaken}><Icon name={taken ? "logout" : "user"} size={14} />{taken ? `Hand back to ${agentName}` : "Take over"}</button>
            <button className="iconbtn" title={railOpen ? "Hide details" : "Show details"} onClick={() => setRailOpen((v) => !v)} style={railOpen ? { background: "var(--color-primary-tint-soft)", color: "var(--color-secondary)" } : null}><Icon name={railOpen ? "chevronRight" : "info"} size={18} /></button>
          </div>
        </div>
        {actionErr && <div style={{ padding: "10px 20px", background: "#fff", borderBottom: "1px solid var(--border-1)" }}><ComposerError msg={actionErr} onDismiss={() => setActionErr(null)} /></div>}
        <div style={{ flex: 1, overflowY: "auto", padding: "20px 24px" }}>
          <div style={{ textAlign: "center", marginBottom: 16 }}><span className="badge badge--neutral" style={{ fontSize: 11 }}>Today</span></div>
          {loading && !detail ? <div style={{ textAlign: "center", color: "var(--fg-4)", fontSize: 13 }}>Loading…</div>
            : (detail ? detail.messages : []).map((m) => <Bubble key={m.id} m={m} convId={detail && detail.id} onChanged={() => { if (detail) API.conversations.get(detail.id).then(setDetail).catch(() => {}); }} />)}
        </div>
        {detail && (taken
          ? <div style={{ borderTop: "1px solid var(--border-1)", background: "#fff" }}>
              <div className="row" style={{ gap: 8, padding: "10px 16px", background: "var(--color-primary-tint-soft)", fontSize: 12.5, color: "var(--fg-2)" }}>
                <Icon name="user" size={15} style={{ color: "var(--color-secondary)" }} /><span><b>{agentName} is paused.</b> You're replying directly — messages send without approval.</span>
              </div>
              <ManualComposer conv={detail} as="you" placeholder={`Reply to ${summary.person} as yourself…`} onChanged={onChanged} />
            </div>
          : detail.pendingDraft
            ? <ApprovalComposer conv={detail} agent={agentName} onChanged={onChanged} />
            : <div style={{ borderTop: "1px solid var(--border-1)", background: "#fff" }}>
                <ManualComposer conv={detail} as="agent" placeholder="Type a message…" onChanged={onChanged} />
              </div>)}
      </div>

      {/* context rail (overlays as a drawer on narrow screens) */}
      {railOpen && <div className="conv__rail-scrim" onClick={() => setRailOpen(false)} />}
      {railOpen && <div className="conv__rail" style={{ borderInlineStart: "1px solid var(--border-1)", background: "#fff", overflowY: "auto", padding: 18 }}>
        <div className="between" style={{ marginBottom: 14 }}>
          <b style={{ fontSize: 13 }}>Lead details</b>
          <button className="iconbtn" style={{ width: 30, height: 30 }} title="Hide" onClick={() => setRailOpen(false)}><Icon name="x" size={16} /></button>
        </div>
        <div className="col" style={{ alignItems: "center", textAlign: "center", marginBottom: 18 }}>
          <Avatar name={summary.person} color={summary.color} size="lg" />
          <div style={{ fontWeight: 700, marginTop: 10 }}>{summary.name}</div>
          <div style={{ fontSize: 12, color: "var(--fg-4)" }}>{summary.person}</div>
        </div>
        {contact && <>
          <div style={{ background: "var(--color-primary-tint-soft)", border: "1px solid var(--color-primary-tint)", borderRadius: 14, padding: 14, marginBottom: 16 }}>
            <div className="row" style={{ gap: 6, marginBottom: 6 }}><Icon name="sparkles" size={15} style={{ color: "var(--color-secondary)" }} /><b style={{ fontSize: 12, color: "var(--color-secondary)" }}>What to do next</b></div>
            <div style={{ fontSize: 13, lineHeight: 1.5 }}>{contact.reco}</div>
          </div>
          <div className="col" style={{ gap: 12 }}>
            <div className="between"><span className="muted" style={{ fontSize: 12 }}>Heat</span><ScoreBar value={contact.heat} color="var(--color-orange)" /></div>
            <div className="between"><span className="muted" style={{ fontSize: 12 }}>Trust</span><ScoreBar value={contact.trust} /></div>
            <div className="between"><span className="muted" style={{ fontSize: 12 }}>Value</span><ScoreBar value={VALUE_PCT[contact.value]} color="var(--color-secondary)" /></div>
            <div className="between"><span className="muted" style={{ fontSize: 12 }}>Platform</span><Badge tone="neutral">{contact.platform}</Badge></div>
            {contact.sentimentLabel && <div className="between"><span className="muted" style={{ fontSize: 12 }}>Sentiment</span><Badge tone="neutral">{contact.sentimentLabel}</Badge></div>}
            {typeof contact.winProbability === "number" && <div className="between"><span className="muted" style={{ fontSize: 12 }}>Win probability</span><span style={{ fontWeight: 700, fontSize: 13 }}>{contact.winProbability}%</span></div>}
            {contact.nextBestAction && <div style={{ fontSize: 12, color: "var(--fg-3)", lineHeight: 1.5 }}><span className="muted">Next: </span>{contact.nextBestAction}</div>}
          </div>
          <hr className="divider" style={{ margin: "16px 0" }} />
          <div style={{ fontSize: 12, color: "var(--fg-4)", marginBottom: 6, fontWeight: 600 }}>Summary</div>
          <p style={{ fontSize: 13, lineHeight: 1.55, color: "var(--fg-2)" }}>{contact.summary}</p>
          <Button variant="ghost" size="sm" block style={{ marginTop: 14 }} iconEnd="chevronRight" onClick={() => openContact(contact)}>Open full profile</Button>
        </>}
      </div>}
    </div>
  );
}

window.ConversationsScreen = ConversationsScreen;
