/* ==================================================================
   Doubts — Student↔Teacher per-question threads
   ------------------------------------------------------------------
   Left column: list of doubts the calling user can see (test author +
   HoD/admin for the owning school). Tabs filter by status.
   Right column: selected thread — original question, what the student
   picked, the message timeline, and a reply composer (text + image).

   The bell in shell.jsx surfaces 'doubt_raised' / 'doubt_message'
   notifications; clicking one navigates here with the doubt preselected
   (via window.KX.DOUBTS_CONTEXT seeded by app.jsx).
   ================================================================== */

const { Icon: DbIcon } = window.KXUI;

const STATUS_LABEL = { open: "Open", answered: "Replied", resolved: "Resolved" };
const STATUS_CLS   = { open: "amber", answered: "blue", resolved: "green" };

const relTimeD = (iso) => {
  if (!iso) return "";
  const ms = Date.now() - new Date(iso).getTime();
  const s = Math.floor(ms / 1000);
  if (s < 60) return `${s}s ago`;
  if (s < 3600) return `${Math.floor(s/60)}m ago`;
  if (s < 86400) return `${Math.floor(s/3600)}h ago`;
  return `${Math.floor(s/86400)}d ago`;
};

const DoubtsScreen = () => {
  const [items, setItems] = React.useState([]);
  const [counts, setCounts] = React.useState({ open: 0, answered: 0, resolved: 0 });
  const [tab, setTab] = React.useState("open");
  const [selectedId, setSelectedId] = React.useState(() => window.KX?.DOUBTS_CONTEXT?.doubtId || null);
  const [search, setSearch] = React.useState("");
  const [loading, setLoading] = React.useState(true);
  const [err, setErr] = React.useState(null);

  const refresh = React.useCallback(async () => {
    setLoading(true); setErr(null);
    try {
      const [list, c] = await Promise.all([
        window.KXApi.get(`/teacher/doubts${tab === "all" ? "" : `?status=${tab}`}`),
        window.KXApi.get("/teacher/doubts/counts"),
      ]);
      setItems(list || []);
      setCounts(c || { open: 0, answered: 0, resolved: 0 });
    } catch (e) {
      setErr(String(e.message || e));
    } finally { setLoading(false); }
  }, [tab]);

  React.useEffect(() => { refresh(); }, [refresh]);

  // Clear the cross-screen context once we've consumed it. The selectedId
  // is now state-owned so the user can navigate freely from here.
  React.useEffect(() => {
    if (window.KX?.DOUBTS_CONTEXT) {
      // If the context's doubt belongs to a different status tab, switch.
      const ctx = window.KX.DOUBTS_CONTEXT;
      if (ctx.tab && ctx.tab !== tab) setTab(ctx.tab);
      delete window.KX.DOUBTS_CONTEXT;
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const filtered = items.filter((d) => {
    if (!search) return true;
    const q = search.toLowerCase();
    return (
      (d.studentName || "").toLowerCase().includes(q) ||
      (d.studentRoll || "").toLowerCase().includes(q) ||
      (d.testTitle || "").toLowerCase().includes(q) ||
      (d.testDisplayId || "").toLowerCase().includes(q) ||
      (d.qTextPreview || "").toLowerCase().includes(q)
    );
  });

  const selected = filtered.find((d) => d.id === selectedId)
                || items.find((d) => d.id === selectedId)
                || null;

  return (
    <div style={{ display: "grid", gridTemplateColumns: "minmax(360px, 480px) 1fr", height: "100%", overflow: "hidden" }}>
      {/* ─── Left: list ─── */}
      <div style={{ overflow: "auto", padding: "24px 20px", borderRight: "1px solid var(--line)" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 4 }}>
          <span style={{ color: "var(--accent)" }}><DbIcon name="inbox" size={18}/></span>
          <div className="muted" style={{ fontSize: 11, letterSpacing: ".08em", textTransform: "uppercase" }}>Student doubts</div>
        </div>
        <h1 style={{ margin: "4px 0 6px", color: "var(--ink-0)", fontFamily: "'Instrument Serif', serif", fontWeight: 400, fontSize: 28, letterSpacing: "-0.01em" }}>
          Conversations
        </h1>
        <p className="muted" style={{ margin: 0, fontSize: 13, maxWidth: 480 }}>
          Threads opened by students from the report screen. You see threads on tests you authored; HoDs and admins see the whole school.
        </p>

        {/* Tabs */}
        <div style={{ marginTop: 18, display: "flex", gap: 4, borderBottom: "1px solid var(--line)" }}>
          {["open", "answered", "resolved"].map((t) => {
            const active = tab === t;
            return (
              <button key={t} onClick={() => setTab(t)}
                style={{
                  background: "transparent", border: "none", padding: "8px 14px",
                  color: active ? "var(--ink-0)" : "var(--ink-3)",
                  borderBottom: active ? "2px solid var(--accent)" : "2px solid transparent",
                  cursor: "pointer", fontSize: 12.5, fontWeight: active ? 600 : 400,
                  letterSpacing: ".02em",
                }}>
                {STATUS_LABEL[t]}
                <span className={`pill ${STATUS_CLS[t]}`} style={{ marginLeft: 8, fontSize: 9 }}>
                  {counts[t] || 0}
                </span>
              </button>
            );
          })}
        </div>

        {/* Search */}
        <div style={{ position: "relative", marginTop: 12 }}>
          <span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--ink-3)" }}>
            <DbIcon name="search" size={12}/>
          </span>
          <input type="text" value={search} onChange={(e) => setSearch(e.target.value)}
            placeholder="Search student, test, question…"
            style={{
              width: "100%", padding: "8px 10px 8px 30px", fontSize: 12.5,
              background: "var(--bg-2)", border: "1px solid var(--line)",
              borderRadius: 6, color: "var(--ink-0)",
            }}/>
        </div>

        {err && <div className="muted" style={{ marginTop: 14, color: "var(--madder, #b14a4a)", fontSize: 12 }}>{err}</div>}
        {loading && <div className="muted" style={{ marginTop: 16, fontSize: 12 }}>Loading…</div>}

        <div style={{ marginTop: 12, display: "flex", flexDirection: "column", gap: 6 }}>
          {!loading && filtered.length === 0 && (
            <div className="cx-emptycard">
              No {STATUS_LABEL[tab].toLowerCase()} doubts.
            </div>
          )}
          {filtered.map((d) => {
            const active = d.id === selectedId;
            return (
              <button key={d.id} onClick={() => setSelectedId(d.id)}
                style={{
                  textAlign: "left", padding: "10px 12px",
                  background: active ? "rgba(255,186,90,0.08)" : "var(--bg-2)",
                  border: `1px solid ${active ? "var(--accent)" : "var(--line)"}`,
                  borderRadius: 8, cursor: "pointer", display: "flex", flexDirection: "column", gap: 4,
                }}>
                <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                  <span className={`pill ${STATUS_CLS[d.status]}`} style={{ fontSize: 9 }}>{STATUS_LABEL[d.status]}</span>
                  <span style={{ color: "var(--ink-2)", fontSize: 11, fontFamily: "var(--mono, monospace)" }}>
                    Q{d.qNo}
                  </span>
                  <span style={{ color: "var(--ink-3)", fontSize: 10, marginLeft: "auto" }}>{relTimeD(d.lastAt || d.updatedAt)}</span>
                </div>
                <div style={{ color: "var(--ink-0)", fontSize: 12.5 }}>
                  <b>{d.studentName}</b> <span className="muted" style={{ fontSize: 11 }}>({d.studentRoll})</span>
                  &nbsp;·&nbsp; <span className="muted">{d.testDisplayId}</span>
                </div>
                <div className="muted" style={{ fontSize: 11.5, lineHeight: 1.35,
                  overflow: "hidden", textOverflow: "ellipsis", display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical" }}>
                  {d.lastSender === "teacher" ? "↪ " : ""}{d.lastBody || d.qTextPreview}
                </div>
              </button>
            );
          })}
        </div>
      </div>

      {/* ─── Right: detail ─── */}
      {selected ? (
        <DoubtDetail key={selected.id} doubtId={selected.id} onRefresh={refresh}/>
      ) : (
        <div style={{ display: "grid", placeItems: "center", color: "var(--ink-3)", fontSize: 13 }}>
          Select a doubt to read and reply.
        </div>
      )}
    </div>
  );
};

// Render any $…$ / \(…\) / \[…\] math inside a container after React has
// flushed. KaTeX's auto-render lib is loaded via index.html. We swallow
// failures so an unsupported delimiter doesn't tear down the screen.
const KATEX_DELIMS = [
  { left: "$$", right: "$$", display: true },
  { left: "\\[", right: "\\]", display: true },
  { left: "$",  right: "$",   display: false },
  { left: "\\(", right: "\\)", display: false },
];
const renderMathIn = (el) => {
  if (!el || typeof window.renderMathInElement !== "function") return;
  try {
    window.renderMathInElement(el, {
      delimiters: KATEX_DELIMS,
      throwOnError: false,
      ignoredTags: ["script", "noscript", "style", "textarea", "pre", "code", "input"],
    });
  } catch {}
};

const DoubtDetail = ({ doubtId, onRefresh }) => {
  const [thread, setThread] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [err, setErr] = React.useState(null);
  const [draft, setDraft] = React.useState("");
  const [pending, setPending] = React.useState([]); // [{ kind, url, filename, mime, size }]
  const [uploading, setUploading] = React.useState(false);
  const [sending, setSending] = React.useState(false);
  const fileRef = React.useRef(null);
  const scrollRef = React.useRef(null);
  const mathRootRef = React.useRef(null);

  const load = React.useCallback(async () => {
    setLoading(true); setErr(null);
    try {
      const data = await window.KXApi.get(`/teacher/doubts/${doubtId}`);
      setThread(data);
    } catch (e) {
      setErr(String(e.message || e));
    } finally { setLoading(false); }
  }, [doubtId]);

  React.useEffect(() => { load(); }, [load]);

  // Scroll to the latest message whenever the thread updates.
  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [thread?.messages?.length]);

  // After the thread renders (or its message count grows), pass over the
  // question card + message bodies so KaTeX replaces inline TeX.
  React.useEffect(() => {
    if (thread) renderMathIn(mathRootRef.current);
  }, [thread?.doubt?.id, thread?.messages?.length]);

  const upload = async (file) => {
    if (!file) return;
    setUploading(true); setErr(null);
    try {
      const form = new FormData();
      form.append("file", file);
      const token = window.KXApi.getToken();
      const r = await fetch("/api/teacher/doubts/upload-attachment", {
        method: "POST",
        headers: token ? { authorization: `Bearer ${token}` } : {},
        body: form,
      });
      if (!r.ok) throw new Error(`upload ${r.status}`);
      const att = await r.json();
      setPending((xs) => [...xs, att]);
    } catch (e) {
      setErr(String(e.message || e));
    } finally {
      setUploading(false);
      if (fileRef.current) fileRef.current.value = "";
    }
  };

  const send = async () => {
    const body = draft.trim();
    if (!body && pending.length === 0) return;
    setSending(true); setErr(null);
    try {
      await window.KXApi.post(`/teacher/doubts/${doubtId}/messages`, { body, attachments: pending });
      setDraft(""); setPending([]);
      await load();
      onRefresh?.();
    } catch (e) {
      setErr(String(e.message || e));
    } finally { setSending(false); }
  };

  const resolve = async () => {
    if (!window.confirm("Mark this doubt as resolved? The student is notified.")) return;
    try {
      await window.KXApi.post(`/teacher/doubts/${doubtId}/resolve`, {});
      await load();
      onRefresh?.();
    } catch (e) { setErr(String(e.message || e)); }
  };

  if (loading) return <div className="muted" style={{ padding: 24 }}>Loading…</div>;
  if (err) return <div style={{ padding: 24, color: "var(--madder, #b14a4a)", fontSize: 13 }}>{err}</div>;
  if (!thread) return null;

  const d = thread.doubt;
  const q = thread.question;
  const sr = thread.studentResponse;
  const picked = q && sr?.selectedOptionId ? q.options.find((o) => o.id === sr.selectedOptionId) : null;

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }}>
      {/* Header */}
      <div style={{ padding: "16px 24px", borderBottom: "1px solid var(--line)" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 6 }}>
          <span className={`pill ${STATUS_CLS[d.status]}`} style={{ fontSize: 10 }}>{STATUS_LABEL[d.status]}</span>
          <span style={{ color: "var(--ink-2)", fontSize: 12, fontFamily: "var(--mono, monospace)" }}>
            {d.testDisplayId} · Q{d.qNo}
          </span>
          <span style={{ color: "var(--ink-0)", fontSize: 13 }}>{d.testTitle}</span>
          <div style={{ marginLeft: "auto", display: "flex", gap: 8 }}>
            {d.status !== "resolved" && (
              <button className="btn ghost sm" onClick={resolve} title="Mark resolved">
                <DbIcon name="check" size={12}/> Mark resolved
              </button>
            )}
          </div>
        </div>
        <div className="muted" style={{ fontSize: 12 }}>
          From <b style={{ color: "var(--ink-1)" }}>{d.studentName}</b> ({d.studentRoll})
          &nbsp;·&nbsp; opened {relTimeD(d.createdAt)}
        </div>
      </div>

      {/* Math-renderable region: question card + message bodies. */}
      <div ref={mathRootRef} style={{ display: "contents" }}>

      {/* Question card */}
      {q && (
        <div style={{ padding: "14px 24px", borderBottom: "1px solid var(--line)", background: "var(--bg-2)" }}>
          <div className="muted" style={{ fontSize: 10, letterSpacing: ".08em", textTransform: "uppercase", marginBottom: 4 }}>
            Question · {q.marks} mark{q.marks === 1 ? "" : "s"}
          </div>
          <div style={{ color: "var(--ink-0)", fontSize: 13.5, lineHeight: 1.55, marginBottom: 8 }}>
            {q.text}
          </div>
          {q.options.length > 0 && (
            <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
              {q.options.map((o) => {
                const isCorrect = o.is_correct;
                const isPicked = picked?.id === o.id;
                return (
                  <div key={o.id} style={{
                    padding: "5px 10px", borderRadius: 5, fontSize: 12,
                    border: `1px solid ${isCorrect ? "var(--green, #4bc97b)" : isPicked ? "var(--madder, #b14a4a)" : "var(--line)"}`,
                    background: isCorrect ? "rgba(75,201,123,0.06)" : isPicked ? "rgba(177,74,74,0.06)" : "transparent",
                    color: "var(--ink-1)",
                  }}>
                    <span style={{ fontFamily: "var(--mono, monospace)", marginRight: 6, color: "var(--ink-3)" }}>{o.letter}.</span>
                    {o.text}
                    {isCorrect && <span style={{ marginLeft: 8, color: "var(--green, #4bc97b)", fontSize: 10, textTransform: "uppercase", letterSpacing: ".08em" }}>correct</span>}
                    {isPicked && !isCorrect && <span style={{ marginLeft: 8, color: "var(--madder, #b14a4a)", fontSize: 10, textTransform: "uppercase", letterSpacing: ".08em" }}>student picked</span>}
                    {isPicked && isCorrect && <span style={{ marginLeft: 8, color: "var(--ink-2)", fontSize: 10 }}>(student picked)</span>}
                  </div>
                );
              })}
            </div>
          )}
          {q.expected_answer && (
            <details style={{ marginTop: 8 }}>
              <summary style={{ cursor: "pointer", fontSize: 11, color: "var(--ink-2)" }}>Show stored solution</summary>
              <div style={{ marginTop: 6, fontSize: 12, color: "var(--ink-1)", lineHeight: 1.55, whiteSpace: "pre-wrap" }}>
                {q.expected_answer}
              </div>
            </details>
          )}
        </div>
      )}

      {/* Messages */}
      <div ref={scrollRef} style={{ flex: 1, overflowY: "auto", padding: "16px 24px", display: "flex", flexDirection: "column", gap: 10 }}>
        {thread.messages.length === 0 && <div className="muted" style={{ fontSize: 12 }}>No messages yet.</div>}
        {thread.messages.map((m) => {
          const isTeacher = m.senderType === "teacher";
          return (
            <div key={m.id} style={{ display: "flex", justifyContent: isTeacher ? "flex-end" : "flex-start" }}>
              <div style={{
                maxWidth: "70%", padding: "8px 12px", borderRadius: 8,
                background: isTeacher ? "rgba(255,186,90,0.10)" : "var(--bg-2)",
                border: `1px solid ${isTeacher ? "rgba(255,186,90,0.30)" : "var(--line)"}`,
              }}>
                <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 2 }}>
                  <span style={{ fontSize: 10, fontFamily: "var(--mono, monospace)", color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: ".06em" }}>
                    {isTeacher ? (m.senderName || "Teacher") : (m.senderName || d.studentName)}
                  </span>
                  <span style={{ fontSize: 10, color: "var(--ink-3)" }}>{relTimeD(m.createdAt)}</span>
                </div>
                {m.body && <div style={{ fontSize: 13, color: "var(--ink-0)", whiteSpace: "pre-wrap", lineHeight: 1.5 }}>{m.body}</div>}
                {m.attachments?.length > 0 && (
                  <div style={{ marginTop: 6, display: "flex", flexWrap: "wrap", gap: 6 }}>
                    {m.attachments.map((a, i) =>
                      a.kind === "image" ? (
                        <a key={i} href={a.url} target="_blank" rel="noreferrer">
                          <img src={a.url} alt={a.filename || ""} style={{ maxHeight: 160, borderRadius: 6, border: "1px solid var(--line)" }}/>
                        </a>
                      ) : null
                    )}
                  </div>
                )}
              </div>
            </div>
          );
        })}
      </div>

      </div>
      {/* End math-renderable region */}

      {/* Composer */}
      {d.status !== "resolved" ? (
        <div style={{ padding: "12px 24px", borderTop: "1px solid var(--line)", background: "var(--bg-2)" }}>
          {pending.length > 0 && (
            <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 8 }}>
              {pending.map((a, i) => (
                <div key={i} style={{ position: "relative" }}>
                  <img src={a.url} style={{ height: 48, width: 48, objectFit: "cover", borderRadius: 4, border: "1px solid var(--line)" }}/>
                  <button onClick={() => setPending((xs) => xs.filter((_, j) => j !== i))}
                    style={{
                      position: "absolute", top: -4, right: -4, width: 16, height: 16, borderRadius: 8,
                      background: "var(--madder, #b14a4a)", color: "#fff", border: "none", cursor: "pointer",
                      fontSize: 9, lineHeight: 1,
                    }}>×</button>
                </div>
              ))}
            </div>
          )}
          <div style={{ display: "flex", gap: 8, alignItems: "flex-end" }}>
            <textarea value={draft} onChange={(e) => setDraft(e.target.value)}
              placeholder="Type your reply…" rows={2}
              style={{
                flex: 1, resize: "none", padding: "8px 10px", fontSize: 13,
                background: "var(--bg-1)", border: "1px solid var(--line)",
                borderRadius: 6, color: "var(--ink-0)", fontFamily: "inherit",
              }}/>
            <input ref={fileRef} type="file" accept="image/*" style={{ display: "none" }}
              onChange={(e) => upload(e.target.files?.[0])}/>
            <button className="btn ghost sm" onClick={() => fileRef.current?.click()} disabled={uploading || sending} title="Attach image">
              {uploading ? "…" : <DbIcon name="upload" size={12}/>}
            </button>
            <button className="btn primary sm" onClick={send} disabled={sending || (!draft.trim() && pending.length === 0)}>
              {sending ? "Sending…" : "Send reply"}
            </button>
          </div>
          {err && <div style={{ marginTop: 6, color: "var(--madder, #b14a4a)", fontSize: 11 }}>{err}</div>}
        </div>
      ) : (
        <div style={{ padding: "12px 24px", borderTop: "1px solid var(--line)", color: "var(--ink-3)", fontSize: 12, fontStyle: "italic" }}>
          This doubt is resolved. Re-open by asking the student to follow up from their report.
        </div>
      )}
    </div>
  );
};

window.DoubtsScreen = DoubtsScreen;
