#!/usr/bin/env python3
"""Independent small-instance cross-check for the Rust certificate gate."""

from fractions import Fraction
from pathlib import Path
import random
import subprocess
import sys
import tempfile

HERE = Path(__file__).resolve().parent
ROOT = HERE.parent
BIN = ROOT / "target" / "release" / "check-ap-bound"


def mono_residue_pairs(bits: str, k: int) -> int:
    """Deliberately direct implementation, structurally unlike the Rust loop."""
    q = len(bits)
    return sum(
        len({bits[(a + j * d) % q] for j in range(k)}) == 1
        for a in range(q)
        for d in range(q)
    )


def finite_count(bits: str, k: int, n: int) -> int:
    q = len(bits)
    total = 0
    for d in range(1, (n - 1) // (k - 1) + 1):
        for a in range(1, n - (k - 1) * d + 1):
            values = [bits[(a + j * d - 1) % q] for j in range(k)]
            total += all(value == values[0] for value in values)
    return total


def run_candidate(k: int, bits: str) -> None:
    q = len(bits)
    pairs = mono_residue_pairs(bits, k)
    bound = Fraction(pairs, 2 * (k - 1) * q * q)
    text = (
        "AP_PERIODIC_V1\n"
        f"k {k}\n"
        f"period {q}\n"
        f"colors {bits}\n"
        f"claimed_mono_pairs {pairs}\n"
        f"claimed_bound {bound.numerator}/{bound.denominator}\n"
    )
    with tempfile.NamedTemporaryFile("w", suffix=".txt", delete=False) as handle:
        handle.write(text)
        path = Path(handle.name)
    try:
        completed = subprocess.run([str(BIN), str(path)], text=True, capture_output=True)
        if completed.returncode != 0 or not completed.stdout.startswith("PASS\n"):
            raise AssertionError(
                f"Rust checker rejected independent certificate:\n{text}"
                f"stdout={completed.stdout!r}\nstderr={completed.stderr!r}"
            )
    finally:
        path.unlink()

    # Independently test the residue-pair asymptotic against two direct finite
    # counts.  Multiplication by n^2 is kept rational; the normalized error
    # should shrink on this fixed periodic example.
    coefficient = bound
    n1 = 40 * q
    n2 = 160 * q
    e1 = abs(Fraction(finite_count(bits, k, n1), n1 * n1) - coefficient)
    e2 = abs(Fraction(finite_count(bits, k, n2), n2 * n2) - coefficient)
    if e2 > e1:
        raise AssertionError(
            f"finite-count convergence sanity check failed for k={k}, bits={bits}: "
            f"errors {e1}, {e2}"
        )


def main() -> int:
    if not BIN.is_file():
        print(f"missing checker binary: {BIN}", file=sys.stderr)
        return 2
    random.seed(1186)
    fixed = [(3, "0"), (3, "01"), (4, "000"), (5, "0011"), (6, "010011")]
    random_cases = []
    for _ in range(20):
        q = random.randint(1, 10)
        k = random.randint(3, 8)
        random_cases.append((k, "".join(random.choice("01") for _ in range(q))))
    for k, bits in fixed + random_cases:
        run_candidate(k, bits)
    print(f"cross-check PASS ({len(fixed) + len(random_cases)} certificates)")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
