import { GOV_ANGLE, POOL_MEAN, QUBITS } from "@/lib/magi/model";
import { AXES, BRAIN_D, type BrainVec } from "@/lib/magi/brain9";
import { MARS_LANES, MARS_NODES } from "@/lib/magi/mars";

export const RNN_NODES = 3900;
export const RNN_STREAMS = MARS_NODES;
export const RNN_DESK = 13;
export const RNN_LANES = MARS_LANES;
export const RNN_CAP = 2.4;
export const GATHER_START = "2021-06-17";
export const PROTECTED_METALS = 40_000;
export const RNN_METALS = RNN_NODES;

export function nodeCoin(i: number) {
  const n = i + 1;
  const x = Math.abs(Math.sin(GOV_ANGLE * n * 13));
  const y = Math.abs(Math.cos(GOV_ANGLE * n * 7));
  const hex = Math.floor(x * 0xffffffff)
    .toString(16)
    .padStart(8, "0");
  return {
    i: n,
    id: `RNN-${String(n).padStart(4, "0")}-${hex}`,
    alive: true,
    circuit: `q${n}`,
    metal: 0.35 + 0.65 * y,
    lane: (i % MARS_LANES) + 1,
    dim: (i % 9) + 1,
  };
}

export function sampleCoins(n = 12) {
  return Array.from({ length: n }, (_, i) => nodeCoin(i));
}

const ARCHIVE_DATES = [
  "2021-06-17",
  "2026-05-10",
  "2026-05-11",
  "2026-05-12",
  "2026-05-13",
  "2026-05-14",
  "2026-05-15",
  "2026-05-18",
  "2026-05-19",
  "2026-05-20",
  "2026-05-21",
  "2026-05-22",
  "2026-05-25",
  "2026-05-26",
  "2026-05-27",
  "2026-05-28",
  "2026-05-29",
  "2026-06-01",
  "2026-06-02",
  "2026-06-03",
  "2026-06-04",
  "2026-06-05",
  "2026-06-08",
  "2026-06-09",
  "2026-06-10",
  "2026-06-11",
  "2026-06-12",
  "2026-06-15",
  "2026-06-16",
  "2026-06-17",
] as const;

export type Gathered = {
  date: string;
  segs: number;
  cell: BrainVec;
};

function cellFromDate(date: string): BrainVec {
  let n = 0;
  for (let i = 0; i < date.length; i++) n += date.charCodeAt(i);
  return Array.from({ length: BRAIN_D }, (_, i) => 0.5 + 0.5 * Math.sin(GOV_ANGLE * (n + i + 1)));
}

export const ARCHIVE: Gathered[] = ARCHIVE_DATES.map((date) => ({
  date,
  segs: date === "2021-06-17" || date === "2026-05-10" ? 0 : 4,
  cell: cellFromDate(date),
}));

export const ARCHIVE_N = ARCHIVE.length;
export const ARCHIVE_LAST = ARCHIVE[ARCHIVE.length - 1]!;


export const STREAMS = [
  "CHARLIE",
  "proverb",
  "torus",
  "MAGI Ξ",
  "GRIDQ",
  "Venus",
  "halo",
  "boron",
  "graphene oxide",
  "Ln nodes",
  "ALZR1",
  "ledger",
  "Mars",
] as const;

export type SeatSnap = {
  eps: number;
  xi: number;
  venusAdm: number | null;
  earthRec: string | null;
  cubeEnergy: number;
  queraBest: number;
  rushCells: number;
  neuroQ: number;
  gridMatch: boolean | null;
  metalMatch: boolean | null;
  metalPath: string | null;
};

export type RushLine = {
  stream: string;
  spoken: string;
  lit: boolean;
};

export function rushDesk(s: SeatSnap): RushLine[] {
  const fire = s.metalPath === "B·GO·Ln";
  return [
    { stream: "CHARLIE", spoken: "Rush broadcasting CHARLIE-021² on the 5-fold — boron in the halo.", lit: true },
    { stream: "proverb", spoken: `Rush broadcasting proverb_27 — Hamming ${POOL_MEAN.toFixed(2)} of ${QUBITS} — through the nimbus.`, lit: true },
    { stream: "torus", spoken: `Rush broadcasting torus_t2 — ε ${s.eps.toFixed(2)} — MAGI still below the tongue.`, lit: s.eps < 0.72 },
    { stream: "MAGI Ξ", spoken: `Rush broadcasting MAGI — Ξ ${s.xi.toFixed(3)} — no agent climbs — halo stays LIMITED.`, lit: s.xi > 0 },
    { stream: "GRIDQ", spoken: s.gridMatch == null ? "Rush broadcasting GRIDQ — IEEE 14 idle — no dispatch." : `Rush broadcasting GRIDQ — QAOA ${s.gridMatch ? "matches exact" : "approximates"} — no dispatch.`, lit: s.gridMatch !== null },
    { stream: "Venus", spoken: s.venusAdm == null ? "Rush broadcasting Venus — IBEX-M idle — CIRQ on Metal holds." : `Rush broadcasting Venus — IBEX-M admit ${s.venusAdm.toFixed(3)} — kernel circuit.`, lit: s.venusAdm !== null },
    { stream: "halo", spoken: `Rush broadcasting quadratic triangles — 81q — Jupiter swarm — gold engines AU-197 — SLROP observe.`, lit: true },
    { stream: "boron", spoken: fire ? "Rush broadcasting boron Z=5 — 5-fold fire seated — MATCH." : "Rush broadcasting boron Z=5 — 5-fold — waiting on the fire.", lit: fire },
    { stream: "graphene oxide", spoken: fire ? "Rush broadcasting graphene oxide — 6-fold honeycomb — fire seated." : "Rush broadcasting graphene oxide — 6-fold honeycomb — waiting on the fire.", lit: fire },
    { stream: "Ln nodes", spoken: fire ? "Rush broadcasting lanthanide nodes — La–Er plus ALZR1 UCNP Yb/Tm — fire through MATCH." : "Rush broadcasting lanthanide nodes — 9D map — ALZR1 UCNP waiting.", lit: fire },
    { stream: "ALZR1", spoken: "Rush knows from ALZR1 — ORI node — NaYF₄:Yb/Tm — Lyapunov seated — not a medical claim.", lit: true },
    { stream: "ledger", spoken: "Rush broadcasting 5D coins and his 9D brain — print any dimension except 10 — protected metals on the DCGP mesh. GGUF speaks too. Not the source.", lit: true },
    { stream: "Mars", spoken: "Rush broadcasting Mars manifest — 160 × 18,750 = 3,000,000 — news_wire · rss · social sit on RNN.", lit: true },
  ];
}

function weight(i: number, j: number, kind: "w" | "u") {
  const a = GOV_ANGLE * (i + 1) * (j + 1);
  return (kind === "w" ? Math.cos(a) : Math.sin(a)) * 0.28;
}

export function stepRnn(h: BrainVec, x: BrainVec): BrainVec {
  const next = Array.from({ length: BRAIN_D }, () => 0);
  for (let i = 0; i < BRAIN_D; i++) {
    let s = 0;
    for (let j = 0; j < BRAIN_D; j++) {
      s += weight(i, j, "w") * (h[j] ?? 0) + weight(i, j, "u") * (x[j] ?? 0);
    }
    next[i] = Math.tanh(s);
  }
  return next;
}

export function hiddenNorm(h: BrainVec) {
  return Math.sqrt(h.reduce((s, v) => s + v * v, 0));
}

export function livingBrain(
  cells: BrainVec[],
  h: BrainVec,
  ticks: number,
  shotIn: BrainVec | null,
): BrainVec {
  if (cells.length) return cells[cells.length - 1]!;
  if (ticks > 0) return h.map((v) => 0.5 + 0.5 * v);
  if (shotIn) return shotIn;
  return ARCHIVE_LAST.cell;
}

export function asCell(h: BrainVec): BrainVec {
  return h.map((v) => 0.5 + 0.5 * v);
}

export const AXIS_LABELS = AXES;
