// Paper dossier — restrained, evidence-forward

const sourceCountLabel = (n) => `${n} ${n === 1 ? "source" : "sources"}`;

const QuestionCard = ({ q, paper }) => {
  const cat = AOP_DATA.categories.find((c) => c.id === q.cat);
  const [open, setOpen] = React.useState(false);
  return (
    <article className={`qcard ${open ? "open" : ""}`}>
      <div className="qnum">№ {q.n}</div>
      <div>
        <div style={{ display: "flex", gap: 12, alignItems: "baseline", marginBottom: 10 }}>
          <span className="label" style={{ color: "var(--ink-2)" }}>{cat.name}</span>
          <span className="meta" style={{ color: "var(--ink-3)" }}>·</span>
          <span className="meta" style={{ color: "var(--ink-3)" }}>{sourceCountLabel(q.sources)}</span>
        </div>
        <h3 onClick={() => setOpen(!open)}>{q.q}</h3>
        <p className="short">{q.short}</p>

        <div className="conf-line">
          <ConfBadge c={q.conf} />
          <span className="why">— {q.confWhy}</span>
        </div>

        <div style={{ display: "flex", gap: 12, alignItems: "center", marginTop: 10 }}>
          <button className="reveal" onClick={() => setOpen(!open)}>
            {open ? "Hide reading notes ▴" : "Read in full · evidence ledger · counterpoints · limits ▾"}
          </button>
          <StatusBadge s={q.status} />
        </div>

        {open && (
          <div style={{ marginTop: 18 }}>
            <p className="preview">{q.preview}</p>
            {q.ledger && (
              <div className="ledger">
                <h4>Evidence ledger — claim ↔ source</h4>
                {q.ledger.map((l, i) => (
                  <div key={i} className="ledger-row">
                    <div>{l.claim}</div>
                    <div className="src">[{l.src}]</div>
                  </div>
                ))}
              </div>
            )}
            {q.counterpoints && q.counterpoints.length > 0 && (
              <div style={{ marginTop: 16, borderTop: "1px dashed var(--rule)", paddingTop: 14 }}>
                <h4 style={{ fontFamily: "var(--sans)", fontSize: 10.5, letterSpacing: ".14em", textTransform: "uppercase", color: "var(--ink-3)", fontWeight: 500, margin: "0 0 10px" }}>Counterpoints</h4>
                {q.counterpoints.map((cp, i) => {
                  // Defensive: render as cited only when declared cited AND at
                  // least one related source is attached. Anything else is an
                  // editorial challenge, marked "not citable".
                  const cited = cp.evidenceClass === "cited" && cp.relatedSourceIds && cp.relatedSourceIds.length > 0;
                  return (
                    <div key={i} style={{ padding: "10px 0", borderBottom: i === q.counterpoints.length - 1 ? 0 : "1px dotted var(--rule)" }}>
                      <div style={{ display: "flex", gap: 8, alignItems: "baseline", flexWrap: "wrap", marginBottom: 5 }}>
                        {cited
                          ? <span className="meta" style={{ color: "var(--accent)" }}>Cited counter-evidence</span>
                          : <span className="meta" style={{ color: "var(--conf-low)" }}>Editorial challenge — not citable</span>}
                        {cited && cp.relatedSourceIds.map((sid) => (
                          <span key={sid} className="mono" style={{ color: "var(--accent)", fontSize: 11 }}>[{sid}]</span>
                        ))}
                      </div>
                      <div style={{ fontFamily: "var(--serif)", fontSize: 14.5, color: "var(--ink-2)", lineHeight: 1.55, fontStyle: cited ? "normal" : "italic", maxWidth: 680 }}>
                        {cp.point}
                      </div>
                      {cp.detail && (
                        <div style={{ fontFamily: "var(--serif)", fontSize: 13.5, color: "var(--ink-3)", lineHeight: 1.55, marginTop: 4, maxWidth: 680 }}>
                          {cp.detail}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            )}
            {q.doesNotShow && q.doesNotShow.length > 0 && (
              <div className="callout" style={{ marginTop: 16 }}>
                <h4>What this paper does not show</h4>
                <ul>{q.doesNotShow.map((d, i) => <li key={i}>{d}</li>)}</ul>
              </div>
            )}
            <div style={{ display: "flex", gap: 14, marginTop: 14, fontFamily: "var(--mono)", fontSize: 11, color: "var(--ink-3)" }}>
              <span>Last revised {paper.added} · public draft</span>
              <a href="#" style={{ color: "var(--ink-3)" }}>Suggest a revision →</a>
            </div>
          </div>
        )}
      </div>
    </article>
  );
};

const Dossier = (props) => {
  // Paper-scoped lookups. paperId comes from a prop so the same component
  // can render multiple dossier artboards; defaults to "seyfried" so existing
  // mounts (mobile, library nav) continue to render Seyfried.
  const paperId = (props && props.paperId) || "seyfried";
  const p = AOP_DATA.papers.find((x) => x.id === paperId);
  const categories = AOP_DATA.categories;
  const questions = AOP_DATA.questions.filter((q) => q.paperId === paperId);
  const sources = AOP_DATA.sources.filter((s) => s.paperId === paperId);
  const analysisSteps = (AOP_DATA.analysisSteps || [])
    .filter((s) => s.paperId === paperId && s.visibility !== "private")
    .slice()
    .sort((a, b) => a.order - b.order);
  const stepLabel = (typeof window !== "undefined" && window.stepLabel) ? window.stepLabel : (t) => t;
  const visLabel = (typeof window !== "undefined" && window.visLabel) ? window.visLabel : (v) => v;
  const evidenceClassLabel = (typeof window !== "undefined" && window.evidenceClassLabel) ? window.evidenceClassLabel : (c) => c;
  const sourceClassLabel = (typeof window !== "undefined" && window.sourceClassLabel) ? window.sourceClassLabel : (c) => c;

  const [activeCat, setActiveCat] = React.useState("all");
  const [showLimitsOnly, setShowLimitsOnly] = React.useState(false);

  let visible = activeCat === "all" ? questions : questions.filter((q) => q.cat === activeCat);
  if (showLimitsOnly) visible = visible.filter((q) => q.doesNotShow && q.doesNotShow.length);

  return (
    <div className="frame">
      <TopNav active="library" />

      <div style={{ maxWidth: 1180, margin: "0 auto", padding: "20px 40px 0", fontFamily: "var(--mono)", fontSize: 11, color: "var(--ink-3)", letterSpacing: ".05em" }}>
        <a href="#" data-nav="home" style={{ color: "var(--ink-3)", border: 0 }}>Library</a> / <a href="#" data-nav="index" style={{ color: "var(--ink-3)", border: 0 }}>{p.field}</a> / <span style={{ color: "var(--ink)" }}>{p.authors.split(/\s+and\s+|,|&/)[0].trim().split(/\s+/).pop()}, {p.year}</span>
      </div>

      {/* Title block — slimmer, single column at top, marginalia below */}
      <header style={{ maxWidth: 1180, margin: "0 auto", padding: "28px 40px 32px" }}>
        <div className="eyebrow" style={{ marginBottom: 14 }}>§ DOSSIER · {p.field.toUpperCase()}</div>
        <h1 style={{ fontFamily: "var(--serif)", fontSize: 52, fontWeight: 500, lineHeight: 1.06, letterSpacing: "-0.02em", margin: "0 0 14px", maxWidth: 880 }}>
          {p.displayTitle || p.title}
        </h1>
        {p.displayTitle && p.title !== p.displayTitle && (
          <div style={{ fontFamily: "var(--serif)", fontSize: 15, color: "var(--ink-3)", fontStyle: "italic", marginBottom: 14 }}>
            On: <span style={{ color: "var(--ink-2)" }}>{p.title}</span>
          </div>
        )}
        <div style={{ fontFamily: "var(--serif)", fontSize: 17, fontStyle: "italic", color: "var(--ink-2)", marginBottom: 12 }}>
          {p.authors}
        </div>
        <div style={{ display: "flex", flexWrap: "wrap", gap: "6px 14px", alignItems: "center", fontFamily: "var(--mono)", fontSize: 12, color: "var(--ink-3)" }}>
          <span>{p.venue}, {p.year}</span>
          <span>·</span>
          <a href="#" style={{ fontFamily: "var(--mono)", fontSize: 12 }}>doi:{p.doi}</a>
          <span>·</span>
          <a href="#" style={{ fontFamily: "var(--mono)", fontSize: 12 }}>Read original ↗</a>
        </div>
        <div style={{ display: "flex", gap: 6, marginTop: 14, flexWrap: "wrap" }}>
          {p.tags.map((t) => <Tag key={t}>{t}</Tag>)}
        </div>
      </header>

      {p.safetyNote && (
        <section style={{ maxWidth: 1180, margin: "0 auto", padding: "0 40px 12px" }}>
          <div className="callout">
            <h4>Safety note</h4>
            <p style={{ margin: 0, fontFamily: "var(--serif)", fontSize: 14.5, lineHeight: 1.55, color: "var(--ink-2)" }}>
              {p.safetyNote}
            </p>
          </div>
        </section>
      )}

      <main style={{ maxWidth: 1180, margin: "0 auto", padding: "0 40px" }}>
        {/* Editorial summary — given full reading width */}
        <section style={{ borderTop: "4px double var(--ink)", borderBottom: "1px solid var(--rule)", padding: "32px 0" }}>
          <div style={{ display: "grid", gridTemplateColumns: "60px 1fr 220px", gap: 24, alignItems: "start" }}>
            <div className="meta" style={{ color: "var(--ink-3)", paddingTop: 6 }}>§ 0</div>
            <div>
              <div className="label" style={{ marginBottom: 12 }}>Editorial summary</div>
              <p className="dropcap" style={{ fontSize: 19, lineHeight: 1.6, margin: 0, maxWidth: 660 }}>
                {p.summary}
              </p>
            </div>
            <aside style={{ fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--ink-3)", lineHeight: 1.9 }}>
              <div style={{ display: "flex", justifyContent: "space-between" }}><span>QUESTIONS</span><span style={{ color: "var(--ink)" }}>{p.qCounts.total}</span></div>
              <div style={{ display: "flex", justifyContent: "space-between" }}><span>PUBLISHED</span><span style={{ color: "var(--ink)" }}>{p.qCounts.published}</span></div>
              <div style={{ display: "flex", justifyContent: "space-between" }}><span>SOURCES</span><span style={{ color: "var(--ink)" }}>{sources.length}</span></div>
              <div style={{ display: "flex", justifyContent: "space-between" }}><span>REVIEW</span><span style={{ color: "var(--ink)" }}>Claim audit</span></div>
              <div style={{ display: "flex", justifyContent: "space-between" }}><span>EDITOR</span><span style={{ color: "var(--ink)" }}>{p.editor || "Unassigned"}</span></div>
              <div style={{ display: "flex", justifyContent: "space-between" }}><span>UPDATED</span><span style={{ color: "var(--ink)" }}>{p.updated || "Not yet dated"}</span></div>
            </aside>
          </div>
        </section>

        {/* Filter / nav row — single source of truth, replaces sidebar TOC */}
        <div style={{ position: "sticky", top: 0, background: "var(--paper)", padding: "16px 0", borderBottom: "1px solid var(--rule)", zIndex: 5, marginTop: 0 }}>
          <div className="filterbar" style={{ marginBottom: 8 }}>
            <span className="label" style={{ marginRight: 4 }}>Read by category</span>
            <button className={`pill ${activeCat === "all" ? "active" : ""}`} onClick={() => setActiveCat("all")}>All · {questions.length}</button>
            {categories.map((c) => {
              const n = questions.filter((q) => q.cat === c.id).length;
              if (n === 0) return null;
              return <button key={c.id} className={`pill ${activeCat === c.id ? "active" : ""}`} onClick={() => setActiveCat(c.id)}>§ {c.num} {c.name} <span style={{ opacity: 0.5, marginLeft: 4 }}>{n}</span></button>;
            })}
          </div>
          <div className="filterbar">
            <label className={`switch ${showLimitsOnly ? "on" : ""}`} onClick={() => setShowLimitsOnly(!showLimitsOnly)} style={{ cursor: "pointer" }}>
              <span className="track"><span className="knob"></span></span>
              Show only questions with stated limits
            </label>
            <span style={{ flex: 1 }}></span>
            <span className="meta" style={{ color: "var(--ink-3)" }}>{visible.length} of {questions.length} shown</span>
          </div>
        </div>

        <section style={{ paddingBottom: 60 }}>
          {categories.map((c) => {
            const qs = visible.filter((q) => q.cat === c.id);
            if (qs.length === 0) return null;
            return (
              <div key={c.id} id={c.id}>
                <SectionHead num={c.num} title={c.name} desc={c.desc} />
                {qs.map((q) => <QuestionCard key={q.id} q={q} paper={p} />)}
              </div>
            );
          })}
        </section>

        {/* Analysis trail — process, not evidence. Sits between Q&A and Sources. */}
        {analysisSteps.length > 0 && (
          <section style={{ marginTop: 40 }}>
            <SectionHead
              num="A"
              title="Analysis trail"
              desc="How the dossier's conclusions were reached. The trail is process; the verdict rests on the cited sources and the editorial review above."
            />

            <div className="callout" style={{ marginTop: 18, marginBottom: 24 }}>
              <h4>The LLM is an analytical aid, not evidence</h4>
              <p style={{ margin: 0, fontFamily: "var(--serif)", fontSize: 14.5, lineHeight: 1.55, color: "var(--ink-2)" }}>
                The LLM conversation is not evidence. It is an analytical aid used to generate questions, identify assumptions, and organize source-based review. The final verdict depends on cited sources and editorial review, not on the LLM's authority.
              </p>
              <p style={{ margin: "8px 0 0", fontFamily: "var(--serif)", fontSize: 14.5, lineHeight: 1.55, color: "var(--ink-2)" }}>
                Editorial challenges do not carry the same evidentiary weight as cited counter-evidence and should not be read as published refutations.
              </p>
            </div>

            {analysisSteps.map((step) => {
              // Resolve evidenceClass for objections defensively. Cited only when
              // declared "cited" AND at least one related source is attached;
              // anything else (missing, "editorial", or "cited" with no sources)
              // collapses to "editorial" so a false cited badge cannot appear.
              const isObjection = step.stepType === "objection";
              const hasSources = !!(step.relatedSourceIds && step.relatedSourceIds.length);
              const ec = isObjection
                ? (step.evidenceClass === "cited" && hasSources ? "cited" : "editorial")
                : null;
              const citedObjection = isObjection && ec === "cited";
              const editorialObjection = isObjection && ec === "editorial";

              const loadBearing = step.stepType === "source_check" || step.stepType === "editorial_decision" || citedObjection;
              const processy = step.stepType === "prompt" || step.stepType === "llm_response" || editorialObjection;
              const isExcerpt = step.visibility === "excerpt_only";
              const body = isExcerpt
                ? (step.excerpt || ((step.content || "").slice(0, 220) + (step.content && step.content.length > 220 ? "…" : "")))
                : step.content;
              const wrapClass = loadBearing ? "callout" : "";
              const wrapStyle = loadBearing
                ? { marginTop: 18 }
                : editorialObjection
                  ? { marginTop: 18, padding: "16px 18px", border: "1px dashed var(--rule)", borderLeft: "3px dashed var(--conf-low)", background: "var(--paper-2)" }
                  : { padding: "22px 0", borderTop: "1px solid var(--rule)" };
              return (
                <div key={step.id} className={wrapClass} style={wrapStyle}>
                  <div style={{ display: "flex", gap: 12, alignItems: "baseline", flexWrap: "wrap", marginBottom: 8 }}>
                    <span className="meta" style={{ color: "var(--ink-3)" }}>№ {String(step.order).padStart(2, "0")}</span>
                    <span className="label" style={{ color: "var(--ink-2)" }}>{stepLabel(step.stepType)}</span>
                    <span className="meta" style={{ color: "var(--ink-3)" }}>· {visLabel(step.visibility)}</span>
                    {citedObjection && (
                      <span className="meta" style={{ color: "var(--accent)" }}>· {evidenceClassLabel("cited")}</span>
                    )}
                    {editorialObjection && (
                      <span className="meta" style={{ color: "var(--conf-low)" }}>· {evidenceClassLabel("editorial")} — not citable</span>
                    )}
                  </div>
                  <h3 style={{ fontFamily: "var(--serif)", fontSize: 19, fontWeight: 500, lineHeight: 1.32, margin: "0 0 10px", maxWidth: 720 }}>
                    {step.title}
                  </h3>
                  {body && (
                    <p style={{
                      fontFamily: "var(--serif)",
                      fontSize: 15.5,
                      lineHeight: 1.65,
                      color: loadBearing ? "var(--ink)" : "var(--ink-2)",
                      margin: 0,
                      maxWidth: 720,
                      fontStyle: processy ? "italic" : "normal",
                    }}>
                      {body}
                    </p>
                  )}
                  {isExcerpt && (
                    <div className="meta" style={{ color: "var(--ink-3)", marginTop: 10, fontStyle: "italic" }}>
                      [Full step withheld — visible to admin only.]
                    </div>
                  )}
                  {((step.relatedQuestionIds && step.relatedQuestionIds.length) || (step.relatedSourceIds && step.relatedSourceIds.length)) ? (
                    <div style={{ display: "flex", gap: 10, flexWrap: "wrap", marginTop: 14, alignItems: "center" }}>
                      {step.relatedQuestionIds && step.relatedQuestionIds.map((qid) => {
                        const ref = questions.find((q) => q.id === qid);
                        if (!ref) return null;
                        return <span key={qid} className="tag">№ {ref.n} · {qid}</span>;
                      })}
                      {step.relatedSourceIds && step.relatedSourceIds.map((sid) => {
                        const ref = sources.find((s) => s.n === sid);
                        if (!ref) return null;
                        return <span key={sid} className="meta" style={{ color: "var(--accent)" }}>[{sid}]</span>;
                      })}
                    </div>
                  ) : null}
                </div>
              );
            })}
          </section>
        )}

        {/* Sources */}
        <section style={{ marginTop: 40 }}>
          <SectionHead num="∞" title="Sources used in this dossier" desc="Every claim above is traceable to one of the following — see the evidence ledger inside each answer." />
          {sources.map((s) => (
            <div key={s.n} className="source-item">
              <div className="sn">[{s.n}]</div>
              <div>
                {s.sourceClass && (
                  <div className="label" style={{ color: "var(--ink-3)", marginBottom: 4 }}>
                    {sourceClassLabel(s.sourceClass)}
                  </div>
                )}
                <div className="stitle">{s.title}</div>
                <div className="scite">{s.cite}</div>
              </div>
              <a href="#" className="meta">view ↗</a>
            </div>
          ))}
        </section>
      </main>

      <Footer />
    </div>
  );
};

window.Dossier = Dossier;
