/**
 * # blotter/certify — the determinism certification leg (kestrel-a57.1 slice 2, ADR-0011)
 *
 * `certify(bus)` is **the projector proving its own core invariant**: it re-projects the bus twice and
 * byte-compares the canonical serialized {@link Blotter}. The determinism leg passes iff the two
 * projections are byte-identical (same bus ⇒ byte-identical Blotter). In `sim` — determinism-pass with the
 * paper/live legs `na` — the verdict is `certified`; ANY divergence is fail-closed `not certified`
 * (ADR-0011). The richer paper/live legs (detectors bit-for-bit, fills ⊆ live, lifecycle divergence
 * explained) land with paper/live modes in a57.3; this slice certifies the determinism leg only.
 *
 * This function is the runtime audit of the claim {@link ./project.ts} embeds (`certification.determinism
 * = pass`): in a correct system the embedded claim and this audit agree; a bug that breaks purity (Map
 * iteration order, a leaked wall clock, an RNG) makes the two projections diverge and `certify` refuses.
 */

import type { BusEvent } from "../bus/index.ts";
import { project } from "./project.ts";
import { serialize } from "./serialize.ts";

/** The determinism-leg verdict. `not certified` is the fail-closed outcome of any re-projection divergence. */
export type CertifyVerdict = "certified" | "not certified";

/** The result of {@link certify}: the verdict, the determinism leg, and a reason when it did not certify. */
export interface CertifyResult {
  readonly verdict: CertifyVerdict;
  readonly determinism: "pass" | "fail";
  /** A logged reason on anything other than a clean sim certification (fail-closed, never silent). */
  readonly reason?: string;
}

/**
 * Certify a GRADED bus on the determinism leg: re-project + byte-compare (ADR-0011). Pure — no wall
 * clock, no RNG. Refuses loudly (via {@link project}) if the bus is not a graded bus.
 */
export function certify(bus: readonly BusEvent[]): CertifyResult {
  const a = serialize(project(bus));
  const b = serialize(project(bus));
  if (a !== b) {
    return {
      verdict: "not certified",
      determinism: "fail",
      reason: "re-projection diverged: project(bus) is not byte-identical across two projections (non-deterministic projection, fail-closed, ADR-0011)",
    };
  }
  // The determinism leg passed. In sim the paper/live legs are `na` ⇒ certified; other modes stay
  // uncertified here because their applicable legs are deferred to a57.3 (fail-closed — never over-claim).
  const meta = bus.find((e) => e.stream === "META");
  const mode = meta !== undefined && meta.stream === "META" ? meta.mode : undefined;
  if (mode === "sim") {
    return { verdict: "certified", determinism: "pass" };
  }
  return {
    verdict: "not certified",
    determinism: "pass",
    reason: `mode ${JSON.stringify(mode)}: paper/live certification legs are deferred to a57.3 — determinism passed but the record cannot yet be certified (fail-closed)`,
  };
}
