// ═══════════════════════════════════════════════════════════════════
// KNOWLEDGE BASE — the canonical Compass datapoint register as the
// platform's schema of record, with a per-project capture overlay.
// Every fact the pipeline can know is defined here; the overlay shows
// what THIS project has captured, verified, or still has as a gap.
// ═══════════════════════════════════════════════════════════════════
(function () {
  const { useState } = React;
  const S = window.ONTOLOGY;

  const REQ_TONE = { Required: "accent", Recommended: "info", Optional: "neutral", Auto: "ok", Internal: "warn" };
  const CAP_TONE = { Parsed: "info", Select: "neutral", Upload: "warn", Manual: "neutral", Auto: "ok" };
  const ST_TONE = { verified: "ok", captured: "info", gap: "neutral" };
  const ST_LABEL = { verified: "verified", captured: "captured", gap: "gap", na: "n/a — other asset class" };
  const ST_DOT = { verified: "var(--ok)", captured: "var(--accent)", gap: "transparent" };

  const kbMono = (s, extra) => <span style={{ fontFamily: "var(--mono)", fontSize: "8.5px", letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--ink-4)", ...extra }}>{s}</span>;

  function StatusDot({ st }) {
    if (st === "na") return <span title="n/a — not in this project's asset class" style={{ width: 9, height: 2, borderRadius: 2, flex: "0 0 auto", background: "var(--rule-hard)", display: "inline-block" }}></span>;
    return <span title={ST_LABEL[st]} style={{ width: 9, height: 9, borderRadius: 999, flex: "0 0 auto",
      background: ST_DOT[st], border: st === "gap" ? "1.5px solid var(--rule-hard)" : "none", display: "inline-block" }}></span>;
  }

  function Bar({ cov }) {
    const w = (n) => (cov.total ? (n / cov.total) * 100 : 0) + "%";
    return (
      <span style={{ display: "inline-flex", width: "100%", height: 6, borderRadius: 3, overflow: "hidden", background: "var(--bg-3)" }}>
        <span style={{ width: w(cov.verified), background: "var(--ok)" }}></span>
        <span style={{ width: w(cov.captured), background: "var(--accent)" }}></span>
      </span>
    );
  }

  function KnowledgeBase({ proj, tenant, go, reference }) {
    const [tier, setTier] = useState(S.TIER_ORDER[0]);
    const [groupF, setGroupF] = useState("all");
    const [q, setQ] = useState("");
    const [reqF, setReqF] = useState("all");
    const [overlay, setOverlay] = useState(!reference);
    // bind the overlay to this project's asset class (A01): universal datapoints +
    // its own Class-fields bundle only. The reference view scores the full register.
    const boundClass = reference ? null : (window.AssetClass ? window.AssetClass.of(proj) : null);
    const cov = S.coverage(proj.id, proj.kbFill || 0, boundClass);
    const boundGroup = boundClass ? (S.assetClass(boundClass) || {}).group : null;
    const naGroup = (grp) => !!boundGroup && grp.indexOf("Class fields — ") === 0 && grp !== boundGroup;
    const pickTier = (t) => { setTier(t); setGroupF("all"); };
    const graphRoute = reference ? "kgref" : "graph";

    const ql = q.trim().toLowerCase();
    const tierGroups = tier === "all" ? S.TIER_ORDER.flatMap((t) => S.groupsByTier[t] || []) : (S.groupsByTier[tier] || []);
    const groups = tierGroups.map((g) => ({
      group: g.group,
      rows: g.codes.map((c) => S.byCode[c]).filter((d) =>
        (reqF === "all" || d.req === reqF) &&
        (!ql || d.name.toLowerCase().includes(ql) || d.code.toLowerCase().includes(ql) || (d.vocab || "").toLowerCase().includes(ql) || (d.desc || "").toLowerCase().includes(ql))),
    })).filter((g) => g.rows.length && (groupF === "all" || g.group === groupF));
    const shown = groups.reduce((a, g) => a + g.rows.length, 0);

    return (
      <div>
        <window.PageHead eyebrow={reference ? "Platform · Canonical reference" : tenant.name + " · " + proj.name} title={reference ? "Datapoint Register" : "Knowledge Base"}
          sub={reference
            ? "The canonical Compass Issuer Datapoint Register — " + S.meta.total + " datapoints across four tiers, the platform-wide schema every project's knowledge base is built against. Each carries its type, capture method, evidence and controlled vocabulary."
            : "The canonical Compass Issuer Datapoint Register — " + S.meta.total + " datapoints across four tiers, every fact the platform can hold, each with its type, capture method, evidence and controlled vocabulary. The overlay shows what this project has captured against the schema."}
          right={
            <div style={{ textAlign: "right" }}>
              {kbMono("register " + S.meta.version, { display: "block", marginBottom: 4, color: "var(--accent-lo)" })}
              {kbMono(S.meta.total + " datapoints · 4 tiers")}
            </div>
          }>
        </window.PageHead>

        {/* coverage summary */}
        {!reference && (
        <div style={{ display: "grid", gridTemplateColumns: "200px repeat(4, 1fr)", gap: 1, background: "var(--rule)", border: "1px solid var(--rule-hard)", borderRadius: "var(--r-3)", overflow: "hidden", marginBottom: 18 }}>
          <div style={{ background: "var(--bg-2)", padding: "13px 15px" }}>
            {kbMono("record completeness", { display: "block", marginBottom: 6 })}
            <div style={{ display: "flex", alignItems: "baseline", gap: 6 }}>
              <span style={{ fontFamily: "var(--display)", fontWeight: 700, fontSize: "26px", lineHeight: 1, color: "var(--ink)" }}>{cov.pct}%</span>
              <span style={{ fontFamily: "var(--mono)", fontSize: "10px", color: "var(--ink-4)" }}>{cov.filled}/{cov.total.total}</span>
            </div>
            <div style={{ marginTop: 8 }}><Bar cov={cov.total}></Bar></div>
          </div>
          {S.TIER_ORDER.map((t) => {
            const c = cov.byTier[t]; const m = S.tierMeta(t);
            return (
              <button key={t} onClick={() => pickTier(t)} style={{ textAlign: "left", border: "none", cursor: "pointer", background: tier === t ? "var(--accent-bg)" : "var(--bg)", padding: "13px 15px", borderTop: tier === t ? "2px solid var(--accent)" : "2px solid transparent" }}>
                <div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 6 }}>
                  <span style={{ fontFamily: "var(--mono)", fontSize: "13px", color: tier === t ? "var(--accent)" : "var(--ink-4)" }}>{m.glyph}</span>
                  {kbMono(t, { color: tier === t ? "var(--accent-lo)" : "var(--ink-3)" })}
                </div>
                <div style={{ display: "flex", alignItems: "baseline", gap: 5 }}>
                  <span style={{ fontFamily: "var(--display)", fontWeight: 700, fontSize: "20px", lineHeight: 1, color: "var(--ink)" }}>{c.verified + c.captured}</span>
                  <span style={{ fontFamily: "var(--mono)", fontSize: "9.5px", color: "var(--ink-4)" }}>/ {c.total}</span>
                </div>
                <div style={{ marginTop: 8 }}><Bar cov={c}></Bar></div>
              </button>
            );
          })}
        </div>
        )}

        {/* filters */}
        <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap", marginBottom: 14 }}>
          {reference ? (
            <div style={{ display: "inline-flex", gap: 4 }}>
              {S.TIER_ORDER.map((t) => {
                const on = tier === t;
                return (
                  <button key={t} onClick={() => pickTier(on ? "all" : t)} title={on ? "Unselect — show all tiers" : "Filter to " + t + " datapoints"} style={{ display: "inline-flex", alignItems: "center", gap: 6, fontFamily: "var(--mono)", fontSize: "9.5px", letterSpacing: "0.06em", textTransform: "uppercase", fontWeight: 600, cursor: "pointer", color: on ? "var(--accent-lo)" : "var(--ink-3)", border: "1px solid " + (on ? "var(--accent-bd)" : "var(--rule-hard)"), background: on ? "var(--accent-bg)" : "var(--bg)", borderRadius: "var(--r-2)", padding: "7px 11px" }}>
                    <span style={{ fontFamily: "var(--mono)", fontSize: "12px", color: on ? "var(--accent)" : "var(--ink-4)" }}>{S.tierMeta(t).glyph}</span>{t} <span style={{ opacity: 0.6 }}>{S.tierCount(t)}</span>
                  </button>
                );
              })}
            </div>
          ) : (
          <span style={{ display: "inline-flex", alignItems: "center", gap: 7, fontFamily: "var(--mono)", fontSize: "9.5px", letterSpacing: "0.06em", textTransform: "uppercase", fontWeight: 600, color: "var(--accent-lo)", border: "1px solid var(--accent-bd)", background: "var(--accent-bg)", borderRadius: "var(--r-2)", padding: "7px 12px" }}>
            <span style={{ fontFamily: "var(--mono)", fontSize: "12px" }}>{S.tierMeta(tier).glyph}</span>{tier} <span style={{ opacity: 0.6 }}>{S.tierCount(tier)}</span>
          </span>
          )}
          <select value={groupF} onChange={(e) => setGroupF(e.target.value)} title="Jump to a group within this tier" style={{ border: "1px solid var(--rule-hard)", borderRadius: "var(--r-2)", background: "var(--bg)", color: "var(--ink-2)", fontFamily: "var(--mono)", fontSize: "10px", padding: "7px 9px", cursor: "pointer", maxWidth: 230 }}>
            <option value="all">All groups ({tierGroups.length})</option>
            {tierGroups.map((g) => <option key={g.group} value={g.group}>{g.group} · {g.codes.length}</option>)}
          </select>
          <select value={reqF} onChange={(e) => setReqF(e.target.value)} style={{ border: "1px solid var(--rule-hard)", borderRadius: "var(--r-2)", background: "var(--bg)", color: "var(--ink-2)", fontFamily: "var(--mono)", fontSize: "10px", padding: "7px 9px", cursor: "pointer" }}>
            {["all", "Required", "Recommended", "Optional", "Auto", "Internal"].map((r) => <option key={r} value={r}>{r === "all" ? "All requirements" : r}</option>)}
          </select>
          <input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search datapoints…" style={{ flex: 1, minWidth: 160, border: "1px solid var(--rule-hard)", borderRadius: "var(--r-2)", background: "var(--bg)", color: "var(--ink)", fontFamily: "var(--ui)", fontSize: "12.5px", padding: "7px 11px" }} />
          {!reference && <button onClick={() => setOverlay((o) => !o)} title="Toggle the project capture overlay" style={{ border: "1px solid " + (overlay ? "var(--accent-bd)" : "var(--rule-hard)"), background: overlay ? "var(--accent-bg)" : "var(--bg)", color: overlay ? "var(--accent-lo)" : "var(--ink-3)", borderRadius: "var(--r-2)", padding: "7px 11px", cursor: "pointer", fontFamily: "var(--mono)", fontSize: "9px", letterSpacing: "0.06em", textTransform: "uppercase", fontWeight: 600 }}>{overlay ? "● capture overlay" : "○ schema only"}</button>}
        </div>

        {/* asset-class lens — universal datapoints + the per-class Asset bundle (A01) */}
        {window.ASSET_AXIS && (
          <div style={{ border: "1px solid var(--accent-bd)", background: "var(--accent-bg)", borderRadius: "var(--r-2)", padding: "10px 13px", marginBottom: 14 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 9, flexWrap: "wrap", marginBottom: 8 }}>
              <button onClick={() => go && go("classes")} title="Open the Asset Classes axis" style={{ border: "none", background: "transparent", padding: 0, cursor: go ? "pointer" : "default", fontFamily: "var(--mono)", fontSize: "9px", fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--accent-lo)", display: "inline-flex", alignItems: "center", gap: 4, textDecoration: "underline", textUnderlineOffset: "2px" }}>Asset-class lens ↗</button>
              <span style={{ fontSize: "var(--fs-xs)", color: "var(--ink-3)" }}>Most datapoints are universal; each class adds its own Asset class-field bundle, selected by A01 · ASSET_CLASS. Jump to a bundle —</span>
            </div>
            <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
              {window.ASSET_AXIS.CLASSES.map((c) => {
                const on = tier === "Asset" && groupF === c.ontology;
                return (
                  <button key={c.id} onClick={() => { if (on) { setGroupF("all"); } else { setTier("Asset"); setGroupF(c.ontology); } }} title={c.bundle.label} style={{ display: "inline-flex", alignItems: "center", gap: 6, fontFamily: "var(--mono)", fontSize: "9px", fontWeight: 600, letterSpacing: "0.03em", cursor: "pointer", color: on ? "#fff" : "var(--ink-2)", border: "1px solid " + (on ? "var(--accent)" : "var(--rule-hard)"), background: on ? "var(--accent)" : "var(--bg)", borderRadius: "var(--r-1)", padding: "5px 9px" }}>
                    <span style={{ fontSize: 11, color: on ? "#fff" : "var(--accent-lo)" }}>{c.glyph}</span>{c.name}<span style={{ opacity: 0.7 }}>{c.fieldCodes.length}</span>
                  </button>
                );
              })}
            </div>
          </div>
        )}

        {/* legend */}
        {overlay && (
          <div style={{ display: "flex", gap: 16, flexWrap: "wrap", marginBottom: 12 }}>
            {[["verified", "var(--ok)", "externally checked"], ["captured", "var(--accent)", "extracted, unverified"], ["gap", "transparent", "not yet captured"]].map(([k, c, note]) => (
              <span key={k} style={{ display: "inline-flex", alignItems: "center", gap: 7 }}>
                <span style={{ width: 9, height: 9, borderRadius: 999, background: c, border: k === "gap" ? "1.5px solid var(--rule-hard)" : "none" }}></span>
                <span style={{ fontFamily: "var(--mono)", fontSize: "9px", letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--ink-3)" }}>{k}</span>
                <span style={{ fontSize: "var(--fs-xs)", color: "var(--ink-4)" }}>· {note}</span>
              </span>
            ))}
          </div>
        )}

        <div style={{ fontFamily: "var(--mono)", fontSize: "9px", letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--ink-4)", marginBottom: 10 }}>{shown} of {tier === "all" ? S.meta.total : S.tierCount(tier)} {tier === "all" ? "" : tier} datapoints · {groups.length} groups</div>

        {groups.map((g) => {
          const gk = tier + "›" + g.group; const gc = cov.byGroup[gk];
          return (
            <div key={g.group} style={{ marginBottom: 14 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 6 }}>
                <window.MonoLabel style={{ color: "var(--ink-2)" }}>{g.group}</window.MonoLabel>
                {overlay && gc && <span style={{ fontFamily: "var(--mono)", fontSize: "9px", color: "var(--ink-4)" }}>{gc.verified + gc.captured}/{gc.total}</span>}
                {overlay && naGroup(g.group) && <span style={{ fontFamily: "var(--mono)", fontSize: "8px", letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--ink-4)", border: "1px solid var(--rule-hard)", borderRadius: "var(--r-1)", padding: "1px 6px" }}>n/a · other class</span>}
                <span style={{ flex: 1, height: 1, background: "var(--rule)" }}></span>
              </div>
              <div style={{ border: "1px solid var(--rule-hard)", borderRadius: "var(--r-3)", overflow: "hidden" }}>
                <div style={{ display: "grid", gridTemplateColumns: (overlay ? "16px " : "") + "62px 1.5fr 92px 104px 96px 104px 76px", gap: 10, padding: "7px 13px", background: "var(--bg-2)", borderBottom: "1px solid var(--rule-hard)" }}>
                  {overlay && <window.MonoLabel></window.MonoLabel>}
                  <window.MonoLabel>Code</window.MonoLabel>
                  <window.MonoLabel>Datapoint</window.MonoLabel>
                  <window.MonoLabel>Type</window.MonoLabel>
                  <window.MonoLabel>Requirement</window.MonoLabel>
                  <window.MonoLabel>Capture</window.MonoLabel>
                  <window.MonoLabel>Vocab</window.MonoLabel>
                  <window.MonoLabel>Visibility</window.MonoLabel>
                </div>
                {g.rows.map((d, i) => {
                  const st = cov.perCode[d.code];
                  return (
                    <div key={d.code} style={{ display: "grid", gridTemplateColumns: (overlay ? "16px " : "") + "62px 1.5fr 92px 104px 96px 104px 76px", gap: 10, alignItems: "start", padding: "10px 13px", borderTop: i ? "1px solid var(--rule-soft)" : "none", background: overlay && st === "gap" ? "var(--bg-2)" : "var(--bg)" }}>
                      {overlay && <span style={{ paddingTop: 4 }}><StatusDot st={st}></StatusDot></span>}
                      <span style={{ fontFamily: "var(--mono)", fontSize: "10px", fontWeight: 600, color: "var(--ink-3)", paddingTop: 2 }}>{d.code}</span>
                      <div>
                        <div style={{ fontFamily: "var(--ui-display)", fontWeight: 600, fontSize: "var(--fs-sm)", color: "var(--ink)", marginBottom: d.desc ? 2 : 0 }}>{d.name}</div>
                        {d.desc ? <p style={{ margin: 0, fontSize: "var(--fs-xs)", color: "var(--ink-4)", lineHeight: 1.5 }}>{d.desc}</p> : null}
                        {d.proof ? <div style={{ marginTop: 4, fontFamily: "var(--mono)", fontSize: "8.5px", letterSpacing: "0.04em", color: "var(--ink-4)" }}>⛉ evidence · {d.proof}</div> : null}
                      </div>
                      <span style={{ fontFamily: "var(--mono)", fontSize: "10px", color: "var(--ink-3)", paddingTop: 2 }}>{d.type}</span>
                      <div style={{ paddingTop: 1 }}><window.Pill tone={REQ_TONE[d.req] || "neutral"}>{d.req}</window.Pill></div>
                      <div style={{ paddingTop: 1 }}><window.Pill tone={CAP_TONE[d.capture] || "neutral"}>{d.capture}</window.Pill></div>
                      <div style={{ paddingTop: 2 }}>
                        {d.vocab ? <button onClick={() => go(graphRoute, { vocab: d.vocab })} title={"Controlled vocabulary · " + d.vocab} style={{ border: "1px solid var(--accent-bd)", background: "var(--accent-bg)", color: "var(--accent-lo)", borderRadius: "var(--r-1)", padding: "2px 7px", cursor: "pointer", fontFamily: "var(--mono)", fontSize: "8.5px", letterSpacing: "0.04em", whiteSpace: "nowrap" }}>{d.vocab}</button> : <span style={{ fontFamily: "var(--mono)", fontSize: "9px", color: "var(--ink-4)" }}>—</span>}
                      </div>
                      <div style={{ paddingTop: 2 }}>
                        <window.Pill tone={d.vis === "Public" ? "ok" : d.vis === "Conditional" ? "warn" : "neutral"}>{d.vis}</window.Pill>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          );
        })}

        <p style={{ margin: "14px 0 0", fontFamily: "var(--mono)", fontSize: "9px", letterSpacing: "0.06em", color: "var(--ink-4)", lineHeight: 1.7 }}>
          Schema source: {S.meta.title} · {S.meta.version} · generated {S.meta.generated}. The tier ontology and controlled vocabularies render on the Knowledge Graph.
        </p>
      </div>
    );
  }

  window.KnowledgeBase = KnowledgeBase;
})();
