// calls.jsx — Call log + single-call detail (live data)

function CallLog({ workspace, onOpen }) {
  const wid = workspace.id;
  const [filter, setFilter] = React.useState("all");
  const [search, setSearch] = React.useState("");
  const [searchInput, setSearchInput] = React.useState("");
  const [cursor, setCursor] = React.useState(null);
  const [accumulated, setAccumulated] = React.useState([]);

  // Reset accumulated rows when filter/search/workspace changes
  React.useEffect(() => {
    setAccumulated([]);
    setCursor(null);
  }, [wid, filter, search]);

  const queryParams = React.useMemo(() => {
    const p = { limit: 25 };
    if (filter === "answered") p.status = "answered";
    else if (filter === "missed") p.status = "missed";
    else if (filter === "qualified") p.qualified = true; // server doesn't filter on this — fine, we'll do client-side too
    if (search) p.search = search;
    if (cursor) p.cursor = cursor;
    return p;
  }, [filter, search, cursor]);

  const list = useApi(() => API.calls.list(wid, queryParams), [wid, JSON.stringify(queryParams)]);

  // Append new page rows when list updates
  React.useEffect(() => {
    if (!list.data) return;
    setAccumulated((prev) => {
      const seen = new Set(prev.map((r) => r.id));
      const fresh = list.data.filter((r) => !seen.has(r.id));
      return [...prev, ...fresh];
    });
  }, [list.data]);

  const meta = list.meta || {};
  const filteredRows = filter === "qualified" ? accumulated.filter((r) => r.qualified) : accumulated;

  // Live updates: when an event arrives, mutate the matching row in place
  // (or prepend a new ringing call). Falls back to a full reload on
  // unknown / missing rows so we never get out of sync.
  useWorkspaceEvents(wid, React.useCallback((msg) => {
    if (!msg?.callId) return;
    if (msg.event === "call.ringing") {
      // New call we don't have yet — prepend a synthesized row so the user
      // sees activity immediately. The full row will arrive via list.reload.
      setAccumulated((prev) => {
        if (prev.some((r) => r.id === msg.callId)) return prev;
        const stub = {
          id: msg.callId,
          callerNumber: msg.data?.fromNumber,
          callerName: null,
          callerLocation: null,
          callerState: null,
          status: "missed",  // optimistic; will update on answer/end
          durationSeconds: 0,
          startedAt: msg.data?.startedAt || new Date().toISOString(),
          qualified: false,
          sentiment: null,
          recordingUrl: null,
          isRepeatCaller: false,
          numberName: msg.data?.friendlyName,
          campaignName: msg.data?.campaign?.name,
          tags: [],
          _live: true,
        };
        return [stub, ...prev];
      });
    } else if (msg.event === "call.answered") {
      setAccumulated((prev) => prev.map((r) => r.id === msg.callId
        ? { ...r, status: "answered" }
        : r));
    } else if (msg.event === "call.ended") {
      setAccumulated((prev) => prev.map((r) => r.id === msg.callId
        ? { ...r, status: msg.data?.disposition === "voicemail" ? "voicemail"
                : msg.data?.disposition === "answered" ? "answered" : "missed",
            durationSeconds: msg.data?.durationSeconds || r.durationSeconds }
        : r));
    } else if (msg.event === "call.recording_ready") {
      setAccumulated((prev) => prev.map((r) => r.id === msg.callId
        ? { ...r, recordingUrl: msg.data?.recordingUrl }
        : r));
    }
  }, []));

  function submitSearch(e) {
    e.preventDefault();
    setSearch(searchInput.trim());
  }

  return (
    <div className="page-inner wide">
      <div className="row between" style={{alignItems:"flex-start", marginBottom: 24}}>
        <div>
          <div className="eyebrow">Tracking</div>
          <h1 className="page-title" style={{marginTop:6}}>Calls</h1>
          <div className="page-sub">Call logs</div>
        </div>
        <div className="row g8">
          <button className="btn btn-secondary btn-sm"><I.filter size={13}/> Filters</button>
          <a
            className="btn btn-secondary btn-sm"
            href={`${API.base}/workspaces/${wid}/calls/export`}
            target="_blank" rel="noopener noreferrer"
          ><I.dl size={13}/> Export CSV</a>
        </div>
      </div>

      <div className="card">
        <div className="card-h" style={{padding:"10px 16px"}}>
          <div className="seg">
            {[
              ["all", "All"], ["answered", "Answered"], ["missed", "Missed"], ["qualified", "Qualified"]
            ].map(([k, l]) => (
              <button key={k} className={filter === k ? "on" : ""} onClick={() => setFilter(k)}>{l}</button>
            ))}
          </div>
          <form onSubmit={submitSearch} className="row g8" style={{marginLeft:"auto"}}>
            <div className="row g8" style={{fontSize:12, color:"var(--ink-4)", padding:"0 8px"}}>
              <I.search size={13}/>
              <input
                value={searchInput}
                onChange={(e) => setSearchInput(e.target.value)}
                placeholder="Search caller or number"
                style={{border:"none", background:"transparent", outline:"none", fontSize:12.5, color:"var(--ink-2)", width:200}}
              />
            </div>
          </form>
        </div>
        <table className="table">
          <thead>
            <tr>
              <th style={{width:40}}></th>
              <th>Caller</th>
              <th>Campaign</th>
              <th>To number</th>
              <th>Sentiment</th>
              <th>Tags</th>
              <th style={{textAlign:"right"}}>Duration</th>
              <th style={{textAlign:"right"}}>When</th>
              <th style={{width:40}}></th>
            </tr>
          </thead>
          <tbody>
            {list.loading && accumulated.length === 0 && (
              <tr><td colSpan="9" style={{textAlign:"center", color:"var(--ink-4)", padding:30}}>Loading…</td></tr>
            )}
            {list.error && (
              <tr><td colSpan="9"><ErrorChip msg={list.error.message}/></td></tr>
            )}
            {!list.loading && filteredRows.length === 0 && (
              <tr><td colSpan="9" style={{textAlign:"center", color:"var(--ink-4)", padding:30}}>No calls match your filters</td></tr>
            )}
            {filteredRows.map((c) => (
              <tr key={c.id} onClick={() => onOpen(c.id)} style={{cursor:"pointer"}}>
                <td>
                  <button className="icon-btn" style={{width:28, height:28, background:"var(--bg-sunken)"}}
                    onClick={(e) => { e.stopPropagation(); onOpen(c.id); }}>
                    <I.play size={11}/>
                  </button>
                </td>
                <td>
                  <div style={{display:"flex", flexDirection:"column"}}>
                    <div className="row g8">
                      <div style={{color:"var(--ink)", fontWeight:500}}>{c.callerName || fmtNumber(c.callerNumber)}</div>
                      {c.isRepeatCaller && <span className="pill info" style={{height:18, fontSize:10}}>Repeat</span>}
                      {c.qualified && <span className="pill good" style={{height:18, fontSize:10}}>Qualified</span>}
                    </div>
                    <div className="num muted" style={{fontSize:12}}>
                      {c.callerName ? `${fmtNumber(c.callerNumber)} · ` : ""}{c.callerLocation || "—"}
                    </div>
                  </div>
                </td>
                <td className="muted">{c.campaignName || "—"}</td>
                <td className="num">{c.numberName || fmtNumber(c.number) || "—"}</td>
                <td>
                  {c.sentiment && (
                    <span className={"pill " + (c.sentiment === "positive" ? "good" : c.sentiment === "negative" ? "bad" : "")}>
                      {c.sentiment}
                    </span>
                  )}
                </td>
                <td>
                  <div className="row g8" style={{flexWrap:"wrap"}}>
                    {(c.tags || []).map((t) => <span key={t} className="pill" style={{fontSize:11}}>{t}</span>)}
                  </div>
                </td>
                <td className="num" style={{textAlign:"right"}}>
                  {c.status === "missed"
                    ? <span className="pill bad" style={{height:18, fontSize:10}}>Missed</span>
                    : fmtDuration(c.durationSeconds)}
                </td>
                <td className="muted num" style={{textAlign:"right", fontSize:12}}>{fmtRelative(c.startedAt)}</td>
                <td><I.chev size={14} style={{color:"var(--ink-4)"}}/></td>
              </tr>
            ))}
          </tbody>
        </table>
        {meta.hasMore && (
          <div style={{padding:14, textAlign:"center", borderTop:".5px solid var(--line)"}}>
            <button className="btn btn-secondary btn-sm" disabled={list.loading}
              onClick={() => setCursor(meta.nextCursor)}>
              {list.loading ? "Loading…" : "Load more"}
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

function CallDetail({ workspace, callId, onBack }) {
  const wid = workspace.id;
  const detail = useApi(() => API.calls.get(wid, callId), [wid, callId]);
  const transcript = useApi(() => API.calls.transcript(wid, callId), [wid, callId]);
  const summary = useApi(() => API.calls.summary(wid, callId), [wid, callId]);
  const notes = useApi(() => API.calls.listNotes(wid, callId), [wid, callId]);

  const [playing, setPlaying] = React.useState(false);
  const [pos, setPos] = React.useState(0);

  const call = detail.data || {};
  const total = call.durationSeconds || 1;

  React.useEffect(() => {
    if (!playing) return;
    const id = setInterval(() => setPos((p) => p >= total ? 0 : Math.min(total, p + 0.4)), 250);
    return () => clearInterval(id);
  }, [playing, total]);

  const wave = React.useMemo(() => Array.from({length: 120}, (_, i) => {
    const t = i / 120;
    return 0.3 + Math.abs(Math.sin(t * 8 + 1.2)) * 0.4 + Math.abs(Math.sin(t * 23)) * 0.3;
  }), []);

  const sentencesByTime = (transcript.data || []).map((t) => ({
    t: fmtTime((t.timestampMs || 0) / 1000),
    spk: (t.speaker || "").charAt(0).toUpperCase() + (t.speaker || "").slice(1),
    text: t.text,
  }));

  const aiSummary = summary.data;
  const callerLine = [call.callerLocation, call.callerState].filter(Boolean).join(", ");

  return (
    <div className="page-inner wide">
      <div className="row g8" style={{marginBottom:16}}>
        <button className="btn btn-ghost btn-sm" onClick={onBack}><I.chev size={13} style={{transform:"rotate(180deg)"}}/> Back to calls</button>
      </div>

      {detail.loading && <div style={{color:"var(--ink-4)", fontSize:13, padding:20}}>Loading call…</div>}
      {detail.error && <ErrorChip msg={detail.error.message}/>}

      {!detail.loading && call.id && (
        <>
          <div className="row between" style={{alignItems:"flex-start", marginBottom:24}}>
            <div>
              <div className="eyebrow row g8">
                Call · {call.startedAt ? new Date(call.startedAt).toLocaleString() : "—"}
                <span className={"pill " + (call.status === "answered" ? "good" : "bad")} style={{height:18, fontSize:10}}>
                  <span className="dot"/>{call.status === "answered" ? "Answered" : call.status === "voicemail" ? "Voicemail" : "Missed"}
                </span>
              </div>
              <h1 className="page-title" style={{marginTop:6}}>{call.callerName || fmtNumber(call.callerNumber)}</h1>
              <div className="page-sub">
                <span className="num">{fmtNumber(call.callerNumber)}</span>
                {callerLine ? <> · {callerLine}</> : null} ·
                <span> called </span>
                <span className="num" style={{color:"var(--ink-2)"}}>{fmtNumber(call.number)}</span>
                {call.campaignName && <>
                  <span> via </span>
                  <span style={{color:"var(--ink-2)"}}>{call.campaignName}</span>
                </>}
              </div>
            </div>
            <div className="row g8">
              {call.recordingUrl && (
                <a className="btn btn-ghost btn-sm" href={call.recordingUrl} target="_blank" rel="noopener noreferrer"><I.dl size={13}/> Download</a>
              )}
              <button className="btn btn-secondary btn-sm"><I.dots size={13}/></button>
            </div>
          </div>

          <div style={{display:"grid", gridTemplateColumns:"1.5fr 1fr", gap:16}}>
            <div className="col g16">
              {/* Waveform card */}
              <div className="card">
                <div className="card-b" style={{padding:20}}>
                  <div className="row g16">
                    <button className="btn btn-primary" style={{width:44, height:44, borderRadius:"50%", padding:0}} onClick={() => setPlaying(!playing)}>
                      {playing ? <I.pause size={16}/> : <I.play size={14}/>}
                    </button>
                    <div style={{flex:1}}>
                      <div className="wave" onClick={(e) => {
                        const r = e.currentTarget.getBoundingClientRect();
                        setPos(((e.clientX - r.left) / r.width) * total);
                      }}>
                        {wave.map((a, i) => {
                          const played = (i / wave.length) <= (pos / total);
                          return <span key={i} style={{height: a * 40 + "px", background: played ? "var(--accent)" : "var(--ink-5)"}} />;
                        })}
                      </div>
                      <div className="row between" style={{marginTop:6, fontSize:11, color:"var(--ink-4)"}}>
                        <span className="num">{fmtTime(pos)}</span>
                        <div className="row g12">
                          <span>1.0×</span>
                          <span>·</span>
                          <span>Agent · Caller</span>
                        </div>
                        <span className="num">{fmtTime(total)}</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>

              {/* AI summary */}
              <div className="card">
                <div className="card-h">
                  <div className="row g8"><I.sparkle size={14} style={{color:"var(--accent)"}}/><h3>AI summary</h3></div>
                  <div className="sub">Auto-generated</div>
                </div>
                <div className="card-b" style={{fontSize:14, color:"var(--ink-2)", lineHeight:1.6}}>
                  {summary.loading && <div style={{color:"var(--ink-4)", fontSize:13}}>Loading summary…</div>}
                  {!summary.loading && !aiSummary && <div style={{color:"var(--ink-4)", fontSize:13}}>No summary available yet.</div>}
                  {aiSummary && (
                    <>
                      <p style={{margin:0}}>{aiSummary.summary}</p>
                      {Array.isArray(aiSummary.actionItems) && aiSummary.actionItems.length > 0 && (
                        <div style={{marginTop:16, paddingTop:14, borderTop:".5px solid var(--line)"}}>
                          <div style={{fontSize:11, fontWeight:600, letterSpacing:".06em", textTransform:"uppercase", color:"var(--ink-4)", marginBottom:10}}>Action items</div>
                          <div className="col g8">
                            {aiSummary.actionItems.map((a, i) => (
                              <div key={i} className="row g8" style={{fontSize:13.5}}>
                                <div style={{width:16, height:16, borderRadius:4, border:"1.2px solid var(--line-2)", marginTop:1, flexShrink:0}}/>
                                <span>{typeof a === "string" ? a : (a.text || JSON.stringify(a))}</span>
                              </div>
                            ))}
                          </div>
                        </div>
                      )}
                      {Array.isArray(aiSummary.keywords) && aiSummary.keywords.length > 0 && (
                        <div style={{marginTop:16, paddingTop:14, borderTop:".5px solid var(--line)"}}>
                          <div style={{fontSize:11, fontWeight:600, letterSpacing:".06em", textTransform:"uppercase", color:"var(--ink-4)", marginBottom:10}}>Keywords</div>
                          <div className="row g8" style={{flexWrap:"wrap"}}>
                            {aiSummary.keywords.map((k) => (
                              <span key={k} className="pill info" style={{fontSize:11.5}}>{k}</span>
                            ))}
                          </div>
                        </div>
                      )}
                    </>
                  )}
                </div>
              </div>

              {/* Transcript */}
              <div className="card">
                <div className="card-h">
                  <h3>Transcript</h3>
                  <div className="row g8" style={{fontSize:12, color:"var(--ink-4)"}}>
                    {sentencesByTime.length} line{sentencesByTime.length === 1 ? "" : "s"}
                  </div>
                </div>
                <div className="card-b">
                  {transcript.loading && <div style={{color:"var(--ink-4)", fontSize:13}}>Loading transcript…</div>}
                  {!transcript.loading && sentencesByTime.length === 0 && (
                    <div style={{color:"var(--ink-4)", fontSize:13}}>No transcript available.</div>
                  )}
                  {sentencesByTime.length > 0 && (
                    <div className="tscript">
                      {sentencesByTime.map((l, i) => (
                        <div key={i} className="tline">
                          <div className="tmeta num">{l.t}</div>
                          <div>
                            <div className="tspk" style={{color: l.spk === "Agent" ? "var(--accent)" : "var(--ink)"}}>{l.spk}</div>
                            <div className="ttext">{l.text}</div>
                          </div>
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              </div>
            </div>

            {/* Right rail */}
            <div className="col g16">
              <div className="card">
                <div className="card-h"><h3>Caller</h3></div>
                <div className="card-b col g12" style={{fontSize:13.5}}>
                  <KV k="Name" v={call.callerName || "Unknown"} />
                  <KV k="Number" v={fmtNumber(call.callerNumber)} mono />
                  <KV k="Location" v={callerLine || "—"} />
                  <KV k="Carrier" v={call.callerCarrier || "—"} />
                  <KV k="Repeat caller" v={call.isRepeatCaller ? "Yes" : "No"} />
                </div>
              </div>

              <div className="card">
                <div className="card-h"><h3>Attribution</h3></div>
                <div className="card-b col g12" style={{fontSize:13.5}}>
                  <KV k="Campaign" v={call.campaignName || "—"} />
                  <KV k="Source" v={call.source || "—"} />
                  <KV k="Medium" v={call.medium || "—"} />
                  <KV k="Keyword" v={call.keyword ? <span className="mono">{call.keyword}</span> : "—"} />
                  <KV k="Landing" v={call.landingPage ? <span className="mono" style={{fontSize:12}}>{call.landingPage}</span> : "—"} />
                  {call.gclid && <KV k="gclid" v={<span className="mono" style={{fontSize:11}}>{call.gclid.slice(0, 14)}…</span>} />}
                </div>
              </div>

              <CallTagsAndNotes
                workspace={workspace}
                callId={callId}
                tags={call.tags || []}
                notes={notes.data || []}
                assignee={call.assignee}
                qualified={call.qualified}
                sentiment={call.sentiment}
                onChanged={() => { detail.reload(); notes.reload(); }}
              />
            </div>
          </div>
        </>
      )}
    </div>
  );
}

function CallTagsAndNotes({ workspace, callId, tags, notes, assignee, qualified, sentiment, onChanged }) {
  const wid = workspace.id;
  const [newTag, setNewTag] = React.useState("");
  const [noteDraft, setNoteDraft] = React.useState("");
  const [busy, setBusy] = React.useState(false);

  async function addTag(e) {
    e.preventDefault();
    const t = newTag.trim();
    if (!t || busy) return;
    setBusy(true);
    try { await API.calls.addTag(wid, callId, t); setNewTag(""); onChanged && onChanged(); }
    catch (err) { window.toast.error(err.message); }
    finally { setBusy(false); }
  }
  async function removeTag(t) {
    setBusy(true);
    try { await API.calls.removeTag(wid, callId, t); onChanged && onChanged(); }
    catch (err) { window.toast.error(err.message); }
    finally { setBusy(false); }
  }
  async function addNote() {
    const c = noteDraft.trim();
    if (!c || busy) return;
    setBusy(true);
    try { await API.calls.addNote(wid, callId, c); setNoteDraft(""); onChanged && onChanged(); }
    catch (err) { window.toast.error(err.message); }
    finally { setBusy(false); }
  }
  async function toggleQualified() {
    setBusy(true);
    try { await API.calls.patch(wid, callId, { qualified: !qualified }); onChanged && onChanged(); }
    catch (err) { window.toast.error(err.message); }
    finally { setBusy(false); }
  }
  async function setSent(v) {
    setBusy(true);
    try { await API.calls.patch(wid, callId, { sentiment: v }); onChanged && onChanged(); }
    catch (err) { window.toast.error(err.message); }
    finally { setBusy(false); }
  }

  return (
    <div className="card">
      <div className="card-h"><h3>Tags & notes</h3></div>
      <div className="card-b col g12">
        <div className="tag-input">
          {tags.map((t) => (
            <span key={t} className="tag" onClick={() => removeTag(t)} style={{cursor:"pointer"}}>{t} <I.x size={10}/></span>
          ))}
          {qualified && <span className="tag" style={{background:"color-mix(in oklab, var(--good) 14%, transparent)", color:"var(--good)"}}>Qualified</span>}
          <form onSubmit={addTag} style={{display:"inline-block"}}>
            <input
              value={newTag}
              onChange={(e) => setNewTag(e.target.value)}
              placeholder="+ Add tag"
              style={{border:"none", background:"transparent", outline:"none", fontSize:12, color:"var(--ink-3)", padding:"2px 6px", width:90}}
            />
          </form>
        </div>

        <div className="row g8" style={{flexWrap:"wrap"}}>
          <button className="btn btn-ghost btn-sm" onClick={toggleQualified} disabled={busy}>
            {qualified ? "Unqualify" : "Mark qualified"}
          </button>
          {["positive", "neutral", "negative"].map((s) => (
            <button key={s} className={"btn btn-ghost btn-sm" + (sentiment === s ? " active" : "")}
              onClick={() => setSent(s)} disabled={busy}>
              {s}
            </button>
          ))}
        </div>

        <textarea className="input" placeholder="Add a note…" rows={3}
          value={noteDraft} onChange={(e) => setNoteDraft(e.target.value)} />
        <button className="btn btn-secondary btn-sm" onClick={addNote} disabled={busy || !noteDraft.trim()}>Add note</button>

        {notes.length > 0 && (
          <div className="col g8" style={{marginTop:6}}>
            {notes.map((n) => (
              <div key={n.id} style={{padding:"10px 12px", background:"var(--bg-sunken)", borderRadius:8, fontSize:13}}>
                <div style={{color:"var(--ink-2)"}}>{n.content}</div>
                <div style={{fontSize:11, color:"var(--ink-4)", marginTop:4}}>
                  {n.authorName || "—"} · {fmtRelative(n.createdAt)}
                </div>
              </div>
            ))}
          </div>
        )}

        {assignee && (
          <div className="row between" style={{paddingTop:8, borderTop:".5px solid var(--line)"}}>
            <div className="row g8" style={{fontSize:12, color:"var(--ink-4)"}}>Assigned to</div>
            <div className="row g8">
              <div style={{width:22, height:22, borderRadius:"50%", background:"linear-gradient(135deg,#F97316,#DB2777)", color:"white", fontSize:10, fontWeight:600, display:"grid", placeItems:"center"}}>
                {(assignee.fullName || assignee.email || "·").split(/\s+/).slice(0, 2).map((w) => w[0]).join("").toUpperCase()}
              </div>
              <span style={{fontSize:13}}>{assignee.fullName || assignee.email}</span>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

function KV({ k, v, mono }) {
  return (
    <div className="row between">
      <div style={{color:"var(--ink-4)", fontSize:12.5}}>{k}</div>
      <div className={mono ? "num" : ""} style={{color:"var(--ink)", fontWeight:500}}>{v}</div>
    </div>
  );
}

function fmtTime(s) {
  s = Math.round(s);
  return Math.floor(s / 60) + ":" + String(s % 60).padStart(2, "0");
}

Object.assign(window, { CallLog, CallDetail, CallTagsAndNotes });
