// ═══════════════════════════════════════════════════════════════════
// INSTANCE KNOWLEDGE GRAPH (per tenant-project)
// The CONCRETE property graph — real entity instances and edges
// extracted from THIS project's parsed artifacts. (The abstract tier
// ontology lives under Platform · Ontology Reference.)
//   · live project  → the real deal-entity graph (window.RaisableInstanceGraph)
//   · other projects → a provenance graph: artifacts → subject → derived entities
// ═══════════════════════════════════════════════════════════════════
(function () {
  const I = window.INTEL;
  const R = window.RAISABLE;

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

  // ── ontology-category styling — the shared visual language (window.OKit),
  // declared once in OntologyKit.jsx and reused by every ontology-typed graph.
  const OK = window.OKit;
  const cgCat = OK.subjCat, cgColor = OK.subjColor, cgGlyph = OK.subjGlyph;

  // ── concrete entity graph from a store.GRAPH {nodes,edges} ────────
  const NW = 116, NH = 46;
  function ConcreteGraph({ graph }) {
    const byId = {}; graph.nodes.forEach((n) => (byId[n.id] = n));
    return (
      <svg viewBox="0 0 980 470" style={{ width: "100%", height: "auto", display: "block", minWidth: 720 }}>
        <defs>
          <marker id="cg-arr" markerWidth="9" markerHeight="9" refX="7.5" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" fill="var(--ink-3)"></path></marker>
          <marker id="cg-arr-r" markerWidth="9" markerHeight="9" refX="7.5" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" fill="var(--err)"></path></marker>
        </defs>
        {graph.edges.map((e, i) => {
          const s = byId[e.from], t = byId[e.to]; if (!s || !t) return null;
          const dx = t.x - s.x, dy = t.y - s.y, len = Math.hypot(dx, dy) || 1;
          const sx = s.x + (dx / len) * 62, sy = s.y + (dy / len) * 28;
          const ex = t.x - (dx / len) * 64, ey = t.y - (dy / len) * 28;
          const stroke = e.risk ? "var(--err)" : "var(--ink-3)";
          return (
            <g key={i}>
              <line x1={sx} y1={sy} x2={ex} y2={ey} stroke={stroke} strokeWidth="1.5" strokeDasharray={e.risk ? "6 5" : "0"} markerEnd={e.risk ? "url(#cg-arr-r)" : "url(#cg-arr)"}></line>
              <text x={(sx + ex) / 2} y={(sy + ey) / 2 - 5} textAnchor="middle" style={{ fontFamily: "var(--mono)", fontSize: "10px" }} fill={e.risk ? "var(--err)" : "var(--ink-4)"}>{e.label}</text>
            </g>
          );
        })}
        {graph.nodes.map((n) => {
          const cat = cgCat(n.of);
          const reified = cat === "reified";
          const dashed = cat === "ref";
          const baseCol = cgColor(n.of);
          const c = n.risk ? "var(--err)" : baseCol;
          const x0 = n.x - NW / 2, y0 = n.y - NH / 2;
          const hex = `${x0},${n.y} ${x0 + 13},${y0} ${x0 + NW - 13},${y0} ${x0 + NW},${n.y} ${x0 + NW - 13},${y0 + NH} ${x0 + 13},${y0 + NH}`;
          return (
            <g key={n.id}>
              {reified ? (
                <polygon points={hex} fill="var(--bg)" stroke={c} strokeWidth="1.6"></polygon>
              ) : (
                <rect x={x0} y={y0} width={NW} height={NH} rx="9" fill="var(--bg)" stroke={c} strokeWidth={dashed ? "1" : "1.6"} strokeDasharray={dashed ? "4 3" : ""}></rect>
              )}
              <text x={n.x} y={n.y - 2} textAnchor="middle" style={{ fontFamily: "var(--ui-display)", fontWeight: 700, fontSize: "13px" }} fill="var(--ink)"><tspan style={{ fontFamily: "var(--mono)", fontWeight: 400 }} fill={baseCol}>{cgGlyph(n.of)} </tspan>{n.label}</text>
              <text x={n.x} y={n.y + 14} textAnchor="middle" style={{ fontFamily: "var(--mono)", fontSize: "9px" }} fill={n.risk ? "var(--err)" : reified ? baseCol : "var(--ink-4)"}>{n.sub}</text>
            </g>
          );
        })}
      </svg>
    );
  }

  const KIND_GLYPH = { pdf: "▤", docx: "▤", html: "◍", md: "≣", xlsx: "▦", zip: "❏", platform: "⬡" };

  // provenance graph for non-live projects: artifacts (left) → subject (centre) → entities (right)
  function ProvenanceGraph({ proj }) {
    const arts = I.artifactsFor(proj).filter((a) => a.status === "parsed");
    const kg = (proj.metrics && proj.metrics.kg) || "—";
    const nEnt = parseInt((kg.match(/(\d+)\s*entit/) || [])[1] || "0", 10);
    const nEdge = parseInt((kg.match(/(\d+)\s*edge/) || [])[1] || "0", 10);
    const H = Math.max(220, arts.length * 56 + 40);
    const subjY = H / 2;
    const aGap = arts.length > 1 ? (H - 80) / (arts.length - 1) : 0;
    return (
      <svg viewBox={"0 0 720 " + H} style={{ width: "100%", maxWidth: 720, height: "auto", display: "block", margin: "0 auto" }}>
        <defs>
          <marker id="ig-arrow" markerWidth="9" markerHeight="9" refX="7.5" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" fill="var(--ink-3)"></path></marker>
        </defs>
        {/* edges artifact -> subject */}
        {arts.map((a, i) => {
          const ay = 40 + i * aGap;
          return <path key={a.id} d={"M170," + ay + " C250," + ay + " 250," + subjY + " 300," + subjY} fill="none" stroke="var(--ink-3)" strokeWidth="1.2" markerEnd="url(#ig-arrow)"></path>;
        })}
        {/* subject -> derived entities */}
        <path d={"M520," + subjY + " C580," + subjY + " 580," + subjY + " 620," + subjY} fill="none" stroke="var(--ink-3)" strokeWidth="1.2" strokeDasharray="2 3" markerEnd="url(#ig-arrow)"></path>
        {/* artifact nodes */}
        {arts.map((a, i) => {
          const ay = 40 + i * aGap;
          return (
            <g key={a.id}>
              <rect x="20" y={ay - 16} width="150" height="32" rx="7" fill="var(--bg)" stroke="var(--rule-hard)"></rect>
              <text x="33" y={ay + 4} style={{ fontFamily: "var(--mono)", fontSize: "13px" }} fill="var(--ink-3)">{KIND_GLYPH[a.kind] || "▢"}</text>
              <text x="50" y={ay + 4} style={{ fontFamily: "var(--mono)", fontSize: "10px" }} fill="var(--ink-2)">{a.id}</text>
            </g>
          );
        })}
        {/* subject node */}
        <rect x="300" y={subjY - 34} width="220" height="68" rx="10" fill="var(--accent-bg)" stroke="var(--accent)" strokeWidth="2"></rect>
        <text x="410" y={subjY - 8} textAnchor="middle" style={{ fontFamily: "var(--ui-display)", fontWeight: 700, fontSize: "14px" }} fill="var(--ink)">{proj.kind}</text>
        <text x="410" y={subjY + 12} textAnchor="middle" style={{ fontFamily: "var(--mono)", fontSize: "9px", letterSpacing: "0.04em" }} fill="var(--accent-lo)">{proj.subject.length > 34 ? proj.subject.slice(0, 33) + "…" : proj.subject}</text>
        {/* derived entities node */}
        <rect x="620" y={subjY - 30} width="84" height="60" rx="8" fill="var(--bg)" stroke="var(--rule-hard)"></rect>
        <text x="662" y={subjY - 6} textAnchor="middle" style={{ fontFamily: "var(--display)", fontWeight: 700, fontSize: "20px" }} fill="var(--ink)">{nEnt || "—"}</text>
        <text x="662" y={subjY + 12} textAnchor="middle" style={{ fontFamily: "var(--mono)", fontSize: "8px", letterSpacing: "0.06em" }} fill="var(--ink-4)">ENTITIES</text>
        {/* labels */}
        <text x="245" y={subjY - 6} textAnchor="middle" style={{ fontFamily: "var(--mono)", fontSize: "9px" }} fill="var(--ink-4)">parsed</text>
        <text x="570" y={subjY - 6} textAnchor="middle" style={{ fontFamily: "var(--mono)", fontSize: "9px" }} fill="var(--ink-4)">resolves</text>
      </svg>
    );
  }

  function InstanceGraph({ proj, tenant, go }) {
    if (proj.live && window.RaisableInstanceGraph) {
      return (
        <div>
          <window.PageHead eyebrow={tenant.name + " · " + proj.name} title="Knowledge Graph"
            sub="The concrete property graph for this project — the actual entity instances and relationships resolved from its parsed artifacts. The abstract tier ontology is under Platform · Ontology Reference."
            right={<div style={{ textAlign: "right" }}>{igMono((proj.metrics && proj.metrics.kg) || "", { color: "var(--accent-lo)" })}</div>}>
          </window.PageHead>
          <window.RaisableInstanceGraph></window.RaisableInstanceGraph>
        </div>
      );
    }
    // store-backed concrete graph (e.g. Lionsgate)
    const store = proj.kbRef && window[proj.kbRef];
    if (store && store.GRAPH) {
      const graphReady = !!(proj.run && proj.run.steps && proj.run.steps.kg === "done");
      const presentCats = OK.CAT_ORDER.filter((k) => store.GRAPH.nodes.some((n) => cgCat(n.of) === k));
      const hasRisk = store.GRAPH.nodes.some((n) => n.risk);
      return (
        <div>
          <window.PageHead eyebrow={tenant.name + " · " + proj.name} title="Knowledge Graph"
            sub="The concrete property graph for this project — the actual entity instances and relationships resolved from its parsed artifacts. Dashed red edges are load-bearing, unverified dependencies. The abstract tier ontology is under Platform · Ontology Reference."
            right={<div style={{ textAlign: "right" }}>{igMono((proj.metrics && proj.metrics.kg) || "", { color: "var(--accent-lo)" })}</div>}>
          </window.PageHead>
          {!graphReady ? (
            <div style={{ border: "1px dashed var(--rule-hard)", borderRadius: "var(--r-3)", background: "var(--bg)", padding: "34px 24px", textAlign: "center" }}>
              <div style={{ fontFamily: "var(--ui-display)", fontWeight: 600, fontSize: "var(--fs-md)", color: "var(--ink)", marginBottom: 6 }}>Graph not yet formed</div>
              <button onClick={() => go("workflow")} style={{ border: "1px solid var(--accent-bd)", background: "var(--accent-bg)", color: "var(--accent-lo)", borderRadius: "var(--r-2)", padding: "8px 16px", cursor: "pointer", fontFamily: "var(--mono)", fontSize: "9.5px", fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase" }}>open workflow ↗</button>
            </div>
          ) : (
            <React.Fragment>
              <div style={{ border: "1px solid var(--rule-hard)", borderRadius: "var(--r-3)", background: "var(--bg)", padding: "18px 16px", marginBottom: 10, overflowX: "auto" }}>
                <ConcreteGraph graph={store.GRAPH}></ConcreteGraph>
                <OK.CategoryLegend cats={presentCats} risk={hasRisk} style={{ paddingTop: 8 }}></OK.CategoryLegend>
                <div style={{ display: "flex", gap: 18, flexWrap: "wrap", justifyContent: "center", paddingTop: 6 }}>
                  {[["structural link", "var(--ink-3)", false], ["at-risk dependency · unverified", "var(--err)", true]].map(([lbl, c, dash]) => (
                    <span key={lbl} style={{ display: "inline-flex", alignItems: "center", gap: 7, fontFamily: "var(--mono)", fontSize: "9px", letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--ink-4)" }}>
                      <span style={{ width: 16, height: 0, borderTop: "2px " + (dash ? "dashed " : "solid ") + c }}></span>{lbl}
                    </span>
                  ))}
                </div>
              </div>
              <p style={{ margin: "10px 0 0", fontFamily: "var(--mono)", fontSize: "9px", letterSpacing: "0.06em", color: "var(--ink-4)", lineHeight: 1.7 }}>
                {store.GRAPH.nodes.length} entities · {store.GRAPH.edges.length} edges, each typed to a World-Model subject and styled by its ontology category. The two red dependencies (land control, IP rights) are unverified — everything downstream inherits their risk.
              </p>
            </React.Fragment>
          )}
        </div>
      );
    }
    const arts = I.artifactsFor(proj).filter((a) => a.status === "parsed");
    // the concrete graph only exists once the Knowledge Graph step has built it
    const graphReady = !!(proj.run && proj.run.steps && proj.run.steps.kg === "done");
    return (
      <div>
        <window.PageHead eyebrow={tenant.name + " · " + proj.name} title="Knowledge Graph"
          sub="The concrete property graph for this project — entity instances resolved from its parsed artifacts. The graph grows as more artifacts are parsed; the abstract ontology is under Platform · Ontology Reference."
          right={<div style={{ textAlign: "right" }}>{igMono((graphReady && proj.metrics && proj.metrics.kg) || "no entities yet", { color: "var(--accent-lo)" })}</div>}>
        </window.PageHead>
        {!graphReady ? (
          <div style={{ border: "1px dashed var(--rule-hard)", borderRadius: "var(--r-3)", background: "var(--bg)", padding: "34px 24px", textAlign: "center" }}>
            <div style={{ fontFamily: "var(--ui-display)", fontWeight: 600, fontSize: "var(--fs-md)", color: "var(--ink)", marginBottom: 6 }}>Graph not yet formed</div>
            <p style={{ margin: "0 auto 14px", maxWidth: 460, fontSize: "var(--fs-sm)", color: "var(--ink-3)", lineHeight: 1.6 }}>Entities resolve once the Knowledge Graph is built in Workflow · 01. This project is at the <b style={{ color: "var(--ink)" }}>{proj.stage}</b> stage{arts.length ? " — " + arts.length + " artifact" + (arts.length > 1 ? "s" : "") + " parsed" : ""}.</p>
            <button onClick={() => go("workflow")} style={{ border: "1px solid var(--accent-bd)", background: "var(--accent-bg)", color: "var(--accent-lo)", borderRadius: "var(--r-2)", padding: "8px 16px", cursor: "pointer", fontFamily: "var(--mono)", fontSize: "9.5px", fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase" }}>open workflow ↗</button>
          </div>
        ) : (
          <React.Fragment>
            <window.SectionHead sub="entity instances resolved from this project's parsed artifacts — provenance from source to subject">Concrete Graph</window.SectionHead>
            <div style={{ border: "1px solid var(--rule-hard)", borderRadius: "var(--r-3)", background: "var(--bg)", padding: "18px 16px", marginBottom: 8 }}>
              <ProvenanceGraph proj={proj}></ProvenanceGraph>
            </div>
            <p style={{ margin: "10px 0 0", fontFamily: "var(--mono)", fontSize: "9px", letterSpacing: "0.06em", color: "var(--ink-4)", lineHeight: 1.7 }}>
              {arts.length} parsed artifacts → {proj.kind} → {(proj.metrics && proj.metrics.kg) || "entities resolving"}. Typed against the ontology under Platform · Ontology Reference.
            </p>
          </React.Fragment>
        )}
      </div>
    );
  }

  Object.assign(window, { InstanceGraph, ConcreteGraph });
})();
