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

export const EXTENSION = { name: "market.mizan.verdict", extends: ["$.CheckoutSessionCompleteRequest.mizan_verdict"],
  schema: "https://mizan.market/verdict/acp-extension.schema.json", spec: "https://mizan.market/verdict/#carriage" };
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; };

/** req: the ACP CheckoutSessionCompleteRequest with the extension active ({mizan_verdict: {token, kid}}), or a
 *  DelegatePaymentRequest carrying metadata.mizan_verdict. merchantId: your identifier as MIZAN knows it. Offline. */
export function acpVerdictOk(req: any, merchantId: string, keys: Record<string, string>, rule: string, now = Date.now() / 1000) {
  const m = req?.mizan_verdict ?? {}, t: string = m.token ?? req?.metadata?.mizan_verdict ?? "";
  if (!t) return { ok: false, code: "no_verdict" };
  const [pre, body, sig] = t.split("."); let c: any;
  try { 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(merchantId)) return { ok: false, code: "payee_mismatch" };
  if (c.rule !== rule || c.bound_to.rule !== rule) return { ok: false, code: "rule_mismatch" };
  if (m.kid && m.kid !== c.kid) return { ok: false, code: "kid_mismatch" };
  return c.decision === "ALLOW" ? { ok: true, code: "valid" } : { ok: false, code: "refused" };
}
