import { createPublicKey, verify } from "node:crypto";

export const HEADER = "Mizan-Verdict"; // value: one mzv1 token. "X-Mizan-Verdict" is read too (earlier spelling).
const SPKI = Buffer.from("302a300506032b6570032100", "hex"), b64u = (s: string) => Buffer.from(s, "base64url");
const norm = (s: unknown) => { const v = String(s ?? "").trim(); return v.toLowerCase().startsWith("0x") ? v.toLowerCase() : v; };

/** headers: request headers (any case). payee: your identifier as MIZAN knows it. rule: the rule hash you require. Offline. */
export function headerVerdictOk(headers: Record<string, string>, payee: string, keys: Record<string, string>, rule: string, now = Date.now() / 1000) {
  const h = Object.fromEntries(Object.entries(headers ?? {}).map(([k, v]) => [k.toLowerCase(), String(v)]));
  const t = (h["mizan-verdict"] ?? h["x-mizan-verdict"] ?? "").trim();
  if (!t) return { ok: false, code: "no_verdict" };
  const [pre, body, sig] = t.split("."); let c: any;
  try { if (/[ ,]/.test(t)) throw 0; c = JSON.parse(b64u(body).toString("utf8")); } catch { return { ok: false, code: "malformed" }; }
  if (pre !== "mzv1" || !keys[c?.kid]) return { ok: false, code: pre !== "mzv1" ? "malformed" : "unknown_kid" };
  const key = createPublicKey({ key: Buffer.concat([SPKI, Buffer.from(keys[c.kid], "base64")]), format: "der", type: "spki" });
  if (!verify(null, Buffer.from(`${pre}.${body}`, "ascii"), key, b64u(sig ?? ""))) return { ok: false, code: "bad_signature" };
  if (c.typ !== "mizan.verdict/1") return { ok: false, code: "malformed" };
  if (!(c.exp > now)) return { ok: false, code: "expired" };
  if (!c.bound_to || norm(c.bound_to.payee) !== norm(payee)) return { ok: false, code: "payee_mismatch" };
  if (c.rule !== rule || c.bound_to.rule !== rule) return { ok: false, code: "rule_mismatch" };
  return c.decision === "ALLOW" ? { ok: true, code: "valid" } : { ok: false, code: "refused" };
}
