/* eslint-disable */
/* ============================================================
   TrustFortress — Narrative Cube components.
   Each cube tells part of the admission flow:
     envelope -> 6 faces (3x3) -> 2 corners -> lease | denial
   ============================================================ */

/* Shared palette — defined here because cube.jsx loads first.
   Exposed as window.T so sections.jsx and app.jsx can both use it. */
const C = {
  ink:        "#0A0E1A",
  inkSoft:    "#121726",
  panel:      "#0F1422",
  hairline:   "rgba(246,245,240,0.08)",
  hairlineSt: "rgba(246,245,240,0.16)",
  paper:      "#F4F1EA",
  paperDeep:  "#EBE6DA",
  ink2:       "#1B2030",
  fg:         "#F5F2EA",
  fgSoft:     "rgba(245,242,234,0.66)",
  fgMute:     "rgba(245,242,234,0.42)",
  violet:     "#7E14FF",
  violetSoft: "#AA3BFF",
  violetWash: "rgba(126,20,255,0.10)",
  ice:        "#E9E2FF",
  amber:      "#E0A23A",
  red:        "#E8553F",
  mint:       "#34D9A4",
  teal:       "#3FB8B0",
  sky:        "#5BA4E6",
};
window.T = C;

/* The six faces, paired into two corners exactly as the architecture doc says:
     Deployment △ = Identity ∧ Lineage ∧ Policy
     Compute △    = Context  ∧ Runtime ∧ Outcome
   Each face has a 3-row band:
     row A : proof / presence
     row B : binding / consistency
     row C : freshness / budget / risk
   This is the 54-check schema (6 faces x 3x3) from the whitepaper.
*/
const FACES = [
  { id: "identity", label: "Identity", q: "WHO",   corner: "deploy",  color: C.violetSoft,
    rows: [
      ["SVID present",   "cert chain",     "PoP valid"],
      ["SPIFFE allowed", "trust domain",   "tenant bound"],
      ["unexpired",      "nonce fresh",    "zone allowed"],
    ]},
  { id: "lineage",  label: "Lineage",  q: "WHERE", corner: "deploy",  color: C.sky,
    rows: [
      ["image signed",   "model signed",   "tools signed"],
      ["signer allowed", "engine = model", "route = policy"],
      ["provenance",     "rekor cache",    "rollout cohort"],
    ]},
  { id: "policy",   label: "Policy",   q: "WHY",   corner: "deploy",  color: C.amber,
    rows: [
      ["bundle signed",  "theorem hash",   "policy hash"],
      ["action allowed", "tenant quota",   "residency ok"],
      ["permit window",  "fail tier",      "target pool"],
    ]},
  { id: "context",  label: "Context",  q: "WHAT",  corner: "compute", color: C.mint,
    rows: [
      ["envelope hash",  "tools hash",     "MM class"],
      ["tokens bound",   "cap bound",      "attn window"],
      ["replay free",    "loop ok",        "ctx-delta ok"],
    ]},
  { id: "runtime",  label: "Runtime",  q: "HOW",   corner: "compute", color: C.teal,
    rows: [
      ["telem epoch",    "attest epoch",   "scheduler hint"],
      ["heads = engine", "kv fits",        "pool health"],
      ["time window",    "epoch fresh",    "host alive"],
    ]},
  { id: "outcome",  label: "Outcome",  q: "WHEN",  corner: "compute", color: C.red,
    rows: [
      ["roofline in",    "retry score",    "preempt sig"],
      ["prefix cache",   "batch ok",       "decode q ok"],
      ["goodput > 0",    "blast radius",   "response cls"],
    ]},
];

/* ----------------------------------------------------------------
   <NarrativeCube>
   A 3D cube whose six faces are the production schema. Each cell
   can be drawn as: pending (dim), pass (face color), fail (red).
   Optional outer ring = current "stage" of the admission flow.
   ---------------------------------------------------------------- */
function NarrativeCube({
  size = 280,
  speed = 28,
  paused = false,
  /* per-face per-cell state: { faceId: [9 booleans|null] } */
  state = null,
  /* which face is highlighted right now */
  highlight = null,
  /* "deploy" | "compute" | null — corner that is currently solving */
  corner = null,
  /* "lease" | "deny" | null */
  verdict = null,
}) {
  const cubeStyle = {
    width: size, height: size,
    transformStyle: "preserve-3d",
    position: "relative",
    animation: paused ? "none" : `tfspin ${speed}s linear infinite`,
  };

  const faceTransforms = {
    identity: `translateZ(${size/2}px)`,                   // front
    lineage:  `rotateY(180deg) translateZ(${size/2}px)`,    // back
    policy:   `rotateY(90deg)  translateZ(${size/2}px)`,    // right
    context:  `rotateY(-90deg) translateZ(${size/2}px)`,    // left
    runtime:  `rotateX(90deg)  translateZ(${size/2}px)`,    // top
    outcome:  `rotateX(-90deg) translateZ(${size/2}px)`,    // bottom
  };

  return (
    <div className="tf-stage" style={{
      width: size, height: size,
      perspective: size * 4,
      display: "inline-block",
      filter: verdict === "deny" ? `drop-shadow(0 0 24px ${C.red}55)` :
              verdict === "lease" ? `drop-shadow(0 0 24px ${C.mint}55)` : "none",
      transition: "filter 0.3s ease",
    }}>
      <div className="tf-cube" style={cubeStyle}>
        {FACES.map((f) => {
          const cells = state?.[f.id];
          const isHi = highlight === f.id;
          const inActiveCorner =
            corner && (
              (corner === "deploy"  && f.corner === "deploy") ||
              (corner === "compute" && f.corner === "compute")
            );
          const accent = f.color;
          const dimColor = inActiveCorner ? `${accent}33` : `${C.fg}10`;
          return (
            <div
              key={f.id}
              style={{
                position: "absolute", inset: 0,
                width: size, height: size,
                transform: faceTransforms[f.id],
                background: `linear-gradient(145deg, ${C.inkSoft}, ${C.panel})`,
                border: `1px solid ${isHi ? accent + "88" : "rgba(245,242,234,0.10)"}`,
                boxShadow: isHi
                  ? `inset 0 0 0 1px ${accent}66, inset 0 0 80px ${accent}30`
                  : `inset 0 0 0 1px rgba(245,242,234,0.04), inset 0 0 60px ${accent}14`,
                display: "grid",
                gridTemplateColumns: "1fr 1fr 1fr",
                gridTemplateRows: "1fr 1fr 1fr",
                gap: size * 0.012,
                padding: size * 0.06,
                transition: "border-color 0.3s, box-shadow 0.3s",
              }}
            >
              {Array.from({ length: 9 }).map((_, i) => {
                const v = cells ? cells[i] : null;
                let bg, bd;
                if (v === true) {
                  bg = `linear-gradient(160deg, ${accent}55, ${accent}18)`;
                  bd = `${accent}66`;
                } else if (v === false) {
                  bg = `linear-gradient(160deg, ${C.red}66, ${C.red}1f)`;
                  bd = `${C.red}88`;
                } else {
                  bg = `linear-gradient(160deg, ${dimColor}, ${dimColor})`;
                  bd = isHi ? `${accent}33` : "rgba(245,242,234,0.06)";
                }
                return (
                  <div key={i} style={{
                    background: bg,
                    border: `1px solid ${bd}`,
                    borderRadius: size * 0.012,
                    transition: "background 0.25s, border-color 0.25s",
                  }} />
                );
              })}
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ----------------------------------------------------------------
   <FlowCube>
   A NarrativeCube driven by a scripted admission timeline. Cycles
   through: envelope -> deploy corner -> compute corner -> verdict.
   Used in the hero. Tells the WHOLE story in ~10 seconds.
   ---------------------------------------------------------------- */
function FlowCube({ size = 320, speed = 36, scenarios }) {
  // default scenario set — alternates pass / various denials
  const defaults = scenarios || [
    {
      label: "GET /v1/chat/completions",
      caller: "agent.invest@trustfortress.io",
      action: "summarize Q4 revenue",
      verdict: "lease",
      lease:  "TFL-7c9a · pool=A100-x8 · ttl=5s",
      faces: {
        identity: [true,true,true, true,true,true, true,true,true],
        lineage:  [true,true,true, true,true,true, true,true,true],
        policy:   [true,true,true, true,true,true, true,true,true],
        context:  [true,true,true, true,true,true, true,true,true],
        runtime:  [true,true,true, true,true,true, true,true,true],
        outcome:  [true,true,true, true,true,true, true,true,true],
      },
    },
    {
      label: "POST /v1/admin/db/drop",
      caller: "agent.coder@dev.trustfortress.io",
      action: "delete prod database",
      verdict: "deny",
      denyCode: "DENY_POLICY",
      denyDim:  "policy · row B · action_class",
      theorem:  "Ramen V1.19.1 #14",
      faces: {
        identity: [true,true,true, true,true,true, true,true,true],
        lineage:  [true,true,true, true,true,true, true,true,true],
        policy:   [true,true,true, false,true,true, true,true,true],
        context:  [true,true,true, true,true,true, true,true,true],
        runtime:  [null,null,null, null,null,null, null,null,null],
        outcome:  [null,null,null, null,null,null, null,null,null],
      },
    },
    {
      label: "POST /v1/embed (24K tokens)",
      caller: "agent.search@trustfortress.io",
      action: "embed long doc, retry #4 in 5min",
      verdict: "deny",
      denyCode: "DENY_OR_SHAPE_GPU",
      denyDim:  "context · row C · loop_ok",
      theorem:  "CubieBridge V1.40 #5",
      faces: {
        identity: [true,true,true, true,true,true, true,true,true],
        lineage:  [true,true,true, true,true,true, true,true,true],
        policy:   [true,true,true, true,true,true, true,true,true],
        context:  [true,true,true, true,true,true, true,true,false],
        runtime:  [true,true,true, true,true,true, null,null,null],
        outcome:  [null,null,null, null,null,null, null,null,null],
      },
    },
  ];

  const [scenarioIdx, setScenarioIdx] = React.useState(0);
  const [stage, setStage] = React.useState(0); // 0=envelope 1=deploy 2=compute 3=verdict
  const [progress, setProgress] = React.useState({ identity:0, lineage:0, policy:0, context:0, runtime:0, outcome:0 });

  const sc = defaults[scenarioIdx % defaults.length];

  React.useEffect(() => {
    let cancelled = false;
    const run = async () => {
      // RESET
      setStage(0);
      setProgress({ identity:0, lineage:0, policy:0, context:0, runtime:0, outcome:0 });
      await sleep(900);
      if (cancelled) return;

      // STAGE 1: Deployment corner — fill identity, lineage, policy in turn
      setStage(1);
      for (const fid of ["identity", "lineage", "policy"]) {
        for (let i = 0; i < 9; i++) {
          if (cancelled) return;
          await sleep(45);
          setProgress((p) => ({ ...p, [fid]: i + 1 }));
        }
        if (sc.faces[fid].includes(false)) {
          // hit a fail — break out into verdict early
          await sleep(400);
          setStage(3);
          await sleep(3200);
          if (cancelled) return;
          setScenarioIdx((s) => s + 1);
          return;
        }
      }
      await sleep(220);
      if (cancelled) return;

      // STAGE 2: Compute corner — context, runtime, outcome
      setStage(2);
      for (const fid of ["context", "runtime", "outcome"]) {
        for (let i = 0; i < 9; i++) {
          if (cancelled) return;
          await sleep(45);
          setProgress((p) => ({ ...p, [fid]: i + 1 }));
        }
        if (sc.faces[fid].includes(false)) {
          await sleep(400);
          setStage(3);
          await sleep(3200);
          if (cancelled) return;
          setScenarioIdx((s) => s + 1);
          return;
        }
      }
      await sleep(260);
      if (cancelled) return;

      // STAGE 3: verdict
      setStage(3);
      await sleep(2800);
      if (cancelled) return;
      setScenarioIdx((s) => s + 1);
    };
    run();
    return () => { cancelled = true; };
  }, [scenarioIdx]);

  // build per-face cell state from progress + scenario
  const state = {};
  FACES.forEach((f) => {
    const filled = progress[f.id];
    state[f.id] = sc.faces[f.id].map((v, i) => i < filled ? v : null);
  });

  const hasFail = (f) => sc.faces[f].includes(false);
  const highlight =
    stage === 1 ? (progress.policy < 9 && !hasFail("identity") && !hasFail("lineage") ? (progress.lineage < 9 && !hasFail("identity") ? (progress.identity < 9 ? "identity" : "lineage") : "policy") : null) :
    stage === 2 ? (progress.outcome < 9 && !hasFail("context") && !hasFail("runtime") ? (progress.runtime < 9 && !hasFail("context") ? (progress.context < 9 ? "context" : "runtime") : "outcome") : null) :
    null;

  const corner = stage === 1 ? "deploy" : stage === 2 ? "compute" : null;
  const verdict = stage === 3 ? sc.verdict : null;

  return (
    <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 22 }}>
      {/* Request envelope */}
      <RequestPill
        method={sc.label.split(" ")[0]}
        path={sc.label.split(" ").slice(1).join(" ")}
        caller={sc.caller}
        action={sc.action}
        active={stage === 0}
      />

      {/* Cube */}
      <NarrativeCube
        size={size}
        speed={speed}
        state={state}
        highlight={highlight}
        corner={corner}
        verdict={verdict}
      />

      {/* Stage rail */}
      <StageRail stage={stage} />

      {/* Verdict pill */}
      <VerdictPill scenario={sc} stage={stage} />
    </div>
  );
}

function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }

function RequestPill({ method, path, caller, action, active }) {
  return (
    <div style={{
      width: "100%", maxWidth: 460,
      padding: "10px 14px",
      background: active ? `${C.violet}14` : "rgba(245,242,234,0.03)",
      border: `1px solid ${active ? C.violet + "55" : "rgba(245,242,234,0.10)"}`,
      borderRadius: 3,
      fontFamily: "var(--mono)", fontSize: 11,
      transition: "all 0.3s",
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
        <span style={{
          padding: "2px 6px", background: C.violet, color: C.fg,
          borderRadius: 2, fontSize: 9, fontWeight: 700, letterSpacing: "0.06em",
        }}>{method}</span>
        <span style={{ color: C.fgSoft, letterSpacing: "0.02em", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{path}</span>
      </div>
      <div style={{ color: C.fgMute, fontSize: 10, letterSpacing: "0.02em" }}>
        caller: <span style={{ color: C.fgSoft }}>{caller}</span> · {action}
      </div>
    </div>
  );
}

function StageRail({ stage }) {
  const stages = [
    { label: "envelope", t: "100µs",  k: 0 },
    { label: "deploy △", t: "+180µs", k: 1 },
    { label: "compute △", t: "+260µs", k: 2 },
    { label: "verdict",  t: "+60µs",  k: 3 },
  ];
  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 6,
      fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.06em",
    }}>
      {stages.map((s, i) => {
        const done = stage > s.k;
        const cur  = stage === s.k;
        const color = cur ? C.violetSoft : done ? C.mint : C.fgMute;
        return (
          <React.Fragment key={s.k}>
            <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
              <span style={{
                width: 6, height: 6, borderRadius: 1,
                background: color,
                boxShadow: cur ? `0 0 0 3px ${color}33` : "none",
                transition: "all 0.2s",
              }} />
              <span style={{ color, fontWeight: cur ? 700 : 400 }}>{s.label}</span>
              <span style={{ color: C.fgMute }}>{s.t}</span>
            </div>
            {i < stages.length - 1 && <span style={{ color: C.fgMute }}>→</span>}
          </React.Fragment>
        );
      })}
    </div>
  );
}

function VerdictPill({ scenario, stage }) {
  if (stage !== 3) {
    return (
      <div style={{
        height: 56, display: "flex", alignItems: "center", justifyContent: "center",
        fontFamily: "var(--mono)", fontSize: 11, color: C.fgMute, letterSpacing: "0.06em",
      }}>
        evaluating · sub-1ms hot path
      </div>
    );
  }
  if (scenario.verdict === "lease") {
    return (
      <div style={{
        padding: "12px 18px",
        background: `${C.mint}12`,
        border: `1px solid ${C.mint}55`,
        borderRadius: 3,
        display: "flex", alignItems: "center", gap: 14,
        fontFamily: "var(--mono)", fontSize: 11,
        animation: "tfFade 0.4s ease",
      }}>
        <span style={{
          padding: "3px 8px", background: C.mint, color: C.ink,
          borderRadius: 2, fontSize: 10, fontWeight: 700, letterSpacing: "0.08em",
        }}>ALLOW</span>
        <span style={{ color: C.fg }}>admission lease minted</span>
        <span style={{ color: C.fgMute }}>{scenario.lease}</span>
      </div>
    );
  }
  return (
    <div style={{
      padding: "12px 18px",
      background: `${C.red}12`,
      border: `1px solid ${C.red}55`,
      borderRadius: 3,
      display: "flex", flexDirection: "column", gap: 6,
      fontFamily: "var(--mono)", fontSize: 11,
      animation: "tfFade 0.4s ease", maxWidth: 460, width: "100%",
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
        <span style={{
          padding: "3px 8px", background: C.red, color: C.fg,
          borderRadius: 2, fontSize: 10, fontWeight: 700, letterSpacing: "0.08em",
        }}>{scenario.denyCode}</span>
        <span style={{ color: C.fg }}>denial certificate emitted</span>
      </div>
      <div style={{ color: C.fgMute, fontSize: 10, paddingLeft: 4 }}>
        failed: {scenario.denyDim} · ⊢ {scenario.theorem}
      </div>
    </div>
  );
}

/* ----------------------------------------------------------------
   <ProblemCube>
   Small static-state cube paired with a denial certificate. Used
   in the Problem section to show exactly which face / row failed.
   ---------------------------------------------------------------- */
function ProblemCube({ size = 96, faces, highlight }) {
  return (
    <NarrativeCube
      size={size}
      speed={20}
      state={faces}
      highlight={highlight}
      verdict={Object.values(faces).some((arr) => arr.includes(false)) ? "deny" : "lease"}
    />
  );
}

/* ----------------------------------------------------------------
   <CornerCube>
   A cube fixed in orientation that shows ONE corner (3 visible
   faces). Used in the Cube section to make the two-corner theorem
   visible. Static, no spin.
   ---------------------------------------------------------------- */
function CornerCube({ size = 220, kind /* "deploy" | "compute" */, label }) {
  const corner = kind === "deploy"
    ? { rotX: -25, rotY: -35, faces: ["identity","lineage","policy"], color: C.violetSoft }
    : { rotX: -25, rotY:  35, faces: ["context","runtime","outcome"], color: C.teal };
  // build a state where every cell on the corner faces is "pass"
  const state = {};
  FACES.forEach((f) => {
    state[f.id] = corner.faces.includes(f.id)
      ? Array(9).fill(true)
      : Array(9).fill(null);
  });
  return (
    <div style={{ width: size, height: size, perspective: size * 4 }}>
      <div style={{
        width: size, height: size,
        transformStyle: "preserve-3d",
        position: "relative",
        transform: `rotateX(${corner.rotX}deg) rotateY(${corner.rotY}deg)`,
      }}>
        <NarrativeCubeStatic size={size} state={state} corner={kind} />
      </div>
    </div>
  );
}

// like NarrativeCube but no animation wrapper (assumes parent handles transform)
function NarrativeCubeStatic({ size, state, corner }) {
  const faceTransforms = {
    identity: `translateZ(${size/2}px)`,
    lineage:  `rotateY(180deg) translateZ(${size/2}px)`,
    policy:   `rotateY(90deg)  translateZ(${size/2}px)`,
    context:  `rotateY(-90deg) translateZ(${size/2}px)`,
    runtime:  `rotateX(90deg)  translateZ(${size/2}px)`,
    outcome:  `rotateX(-90deg) translateZ(${size/2}px)`,
  };
  return FACES.map((f) => {
    const cells = state[f.id];
    const accent = f.color;
    const inCorner =
      (corner === "deploy"  && f.corner === "deploy") ||
      (corner === "compute" && f.corner === "compute");
    return (
      <div key={f.id} style={{
        position: "absolute", inset: 0,
        width: size, height: size,
        transform: faceTransforms[f.id],
        background: `linear-gradient(145deg, ${C.inkSoft}, ${C.panel})`,
        border: `1px solid rgba(245,242,234,0.10)`,
        boxShadow: inCorner
          ? `inset 0 0 0 1px ${accent}55, inset 0 0 70px ${accent}30`
          : `inset 0 0 0 1px rgba(245,242,234,0.04)`,
        display: "grid",
        gridTemplateColumns: "1fr 1fr 1fr",
        gridTemplateRows: "1fr 1fr 1fr",
        gap: size * 0.012,
        padding: size * 0.06,
      }}>
        {Array.from({ length: 9 }).map((_, i) => {
          const v = cells[i];
          let bg, bd;
          if (v === true) {
            bg = `linear-gradient(160deg, ${accent}55, ${accent}18)`;
            bd = `${accent}66`;
          } else {
            bg = `linear-gradient(160deg, ${C.fg}08, ${C.fg}04)`;
            bd = `rgba(245,242,234,0.06)`;
          }
          return <div key={i} style={{ background: bg, border: `1px solid ${bd}`, borderRadius: size*0.012 }}/>;
        })}
        {inCorner && (
          <div style={{
            position: "absolute", left: 8, top: 8,
            fontFamily: "var(--mono)", fontSize: 9, color: accent,
            letterSpacing: "0.12em", fontWeight: 700,
          }}>
            {f.label.toUpperCase()}
          </div>
        )}
      </div>
    );
  });
}

/* ----------------------------------------------------------------
   exports for global scope (Babel separate-script pattern)
   ---------------------------------------------------------------- */
Object.assign(window, {
  NarrativeCube, FlowCube, ProblemCube, CornerCube, FACES,
  TF_C: C,
});
