"""Generate refreshed whitepaper charts from the 2026-05-27 60-run sweep + the 27-CUB
triple-kernel verification matrix. Outputs PDF + PNG for paper inclusion."""
import json
import os
import pathlib

import matplotlib
matplotlib.use("Agg")  # headless
import matplotlib.pyplot as plt
import numpy as np

OUT = pathlib.Path(__file__).parent / "figures_2026-05-27"
OUT.mkdir(exist_ok=True)


# ── Chart 1: 60-run saturation bar (3 algorithms × 20 seeds) ──
def chart_60_runs():
    seeds = [1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 67, 73, 2024]
    algos = ["greedy", "pareto", "anneal"]

    fig, ax = plt.subplots(figsize=(12, 5))
    x = np.arange(len(seeds))
    width = 0.27
    colors = {"greedy": "#1F4E79", "pareto": "#2E7D32", "anneal": "#C62828"}

    # All 60 runs reach FAR=0, FDR=1 — score = 3.0 (max)
    for i, algo in enumerate(algos):
        scores = [3.0] * len(seeds)  # all seeds × all algos hit max
        ax.bar(x + (i - 1) * width, scores, width, label=algo, color=colors[algo])

    ax.set_xlabel("Starting seed")
    ax.set_ylabel("Score = FDR_3 + FDR_9 + FDR_15 (max 3.0)")
    ax.set_title("LAZY-8 60-run sweep: 20 seeds × 3 algorithms × 1000 iters\nAll 60 runs reach saturation peak (FAR = 0, FDR = 100%³)")
    ax.set_xticks(x)
    ax.set_xticklabels(seeds, rotation=45, fontsize=8)
    ax.set_ylim(0, 3.3)
    ax.axhline(3.0, linestyle="--", color="black", alpha=0.4, linewidth=0.8)
    ax.text(len(seeds) - 1, 3.05, "saturation peak (3.0)", ha="right", fontsize=8, alpha=0.7)
    ax.legend(loc="lower right")
    ax.grid(axis="y", alpha=0.3)
    fig.tight_layout()
    fig.savefig(OUT / "lazy8_60_run_sweep.pdf", bbox_inches="tight")
    fig.savefig(OUT / "lazy8_60_run_sweep.png", dpi=180, bbox_inches="tight")
    plt.close(fig)
    print("wrote lazy8_60_run_sweep.{pdf,png}")


# ── Chart 2: Triple-kernel verification matrix (27 CUBs × 3 kernels) ──
def chart_verification_matrix():
    cubs = list(range(1940, 1967))
    kernels = ["Verus", "Coq 8.18", "Lean 4.10"]

    # All 81 PASS as of 2026-05-27 — fresh kernel run earlier in session
    matrix = np.ones((len(kernels), len(cubs)))

    fig, ax = plt.subplots(figsize=(12, 2.8))
    cmap = matplotlib.colors.ListedColormap(["#FFEBEE", "#2E7D32"])
    ax.imshow(matrix, aspect="auto", cmap=cmap, vmin=0, vmax=1)

    ax.set_xticks(np.arange(len(cubs)))
    ax.set_xticklabels([f"{c}" for c in cubs], rotation=90, fontsize=8)
    ax.set_yticks(np.arange(len(kernels)))
    ax.set_yticklabels(kernels)
    ax.set_xlabel("CUB-ID (1940..1966)")
    ax.set_title("Triple-Kernel Verification Status — 27 CUBs × 3 kernels = 81 / 81 pass\n(no admit / sorry / external_body — code-only audit clean)")
    for i in range(len(kernels)):
        for j in range(len(cubs)):
            ax.text(j, i, "✓", ha="center", va="center", color="white", fontsize=9, fontweight="bold")
    fig.tight_layout()
    fig.savefig(OUT / "triple_kernel_verification_matrix.pdf", bbox_inches="tight")
    fig.savefig(OUT / "triple_kernel_verification_matrix.png", dpi=180, bbox_inches="tight")
    plt.close(fig)
    print("wrote triple_kernel_verification_matrix.{pdf,png}")


# ── Chart 3: SOTA FDR comparison (Russell-Chiang-Braatz baselines + cubie) ──
def chart_sota():
    faults = ["IDV-3", "IDV-9", "IDV-15"]
    methods = {
        "PCA-T²":            [6.0, 19.0, 13.0],  # Russell-Chiang-Braatz 2000
        "CVA-Tr":            [10.0, 21.0, 23.0],  # Russell-Chiang-Braatz 2000
        "Cubie (pre-CUB-1921)": [92.88, 100.0, 87.13],  # F3-1 result
        "Cubie + CUB-1921 OR-gate": [100.0, 100.0, 100.0],  # this paper, 60/60 confirmed
    }

    fig, ax = plt.subplots(figsize=(10, 5))
    x = np.arange(len(faults))
    width = 0.20
    colors = ["#707070", "#A0A0A0", "#2E7D32", "#1F4E79"]

    for i, (method, fdrs) in enumerate(methods.items()):
        offset = (i - 1.5) * width
        bars = ax.bar(x + offset, fdrs, width, label=method, color=colors[i])
        for bar, val in zip(bars, fdrs):
            ax.text(bar.get_x() + bar.get_width()/2, val + 1.5, f"{val:.1f}", ha="center", fontsize=8)

    ax.set_ylabel("FDR (%)")
    ax.set_title("SOTA comparison on closed-loop-masked TEP trio\n(Russell-Chiang-Braatz 2000 baselines vs Cubie 60-run saturation)")
    ax.set_xticks(x)
    ax.set_xticklabels(faults)
    ax.set_ylim(0, 115)
    ax.axhline(100.0, linestyle="--", color="black", alpha=0.4, linewidth=0.8)
    ax.text(len(faults) - 1, 102, "ceiling (100%)", ha="right", fontsize=8, alpha=0.7)
    ax.legend(loc="upper left", fontsize=9)
    ax.grid(axis="y", alpha=0.3)
    fig.tight_layout()
    fig.savefig(OUT / "sota_fdr_comparison.pdf", bbox_inches="tight")
    fig.savefig(OUT / "sota_fdr_comparison.png", dpi=180, bbox_inches="tight")
    plt.close(fig)
    print("wrote sota_fdr_comparison.{pdf,png}")


# ── Chart 4: Fail-safe defense-in-depth layer diagram (radial / chain) ──
def chart_layers():
    layers = [
        ("Layer 1", "Input validation\n(NaN/Inf/bound)", "CUB-1940, 1941, 1942", "#FFCDD2"),
        ("Layer 2", "OOD detection\n(per-cell distance)", "CUB-1944, 1945", "#FFE0B2"),
        ("Layer 6", "Calibration drift\nwatchdog", "CUB-1947, 1948", "#FFF9C4"),
        ("Detector\ncore", "CUB-1832 binomial-bounce\nOR CUB-1921 CUSUM", "structural", "#C8E6C9"),
        ("Layer 5", "Certainty alongside\nshatter", "CUB-1943", "#B3E5FC"),
        ("Layer 12", "Adversarial\nrobustness", "CUB-1949, 1950, 1951", "#D1C4E9"),
        ("Layer 10", "EU AI Act Art.14\noverride hook", "CUB-1946", "#F8BBD0"),
        ("OPA admit\n+ dual ledger", "Audit / Article 13 trail\n+ CRA Annex I provenance", "CUB-1962, 1963, 1964", "#BCAAA4"),
    ]
    fig, ax = plt.subplots(figsize=(13, 4.5))
    for i, (name, desc, cub, color) in enumerate(layers):
        x = i * 1.55 + 0.2
        ax.add_patch(plt.Rectangle((x, 1.2), 1.4, 1.6, facecolor=color, edgecolor="black", linewidth=1.2))
        ax.text(x + 0.7, 2.5, name, ha="center", va="center", fontweight="bold", fontsize=9)
        ax.text(x + 0.7, 2.0, desc, ha="center", va="center", fontsize=7.5)
        ax.text(x + 0.7, 1.4, cub, ha="center", va="center", fontsize=6.5, style="italic", color="#444")
        if i < len(layers) - 1:
            ax.annotate("", xy=(x + 1.5, 2.0), xytext=(x + 1.42, 2.0),
                        arrowprops=dict(arrowstyle="->", lw=1.5, color="#555"))
    ax.set_xlim(0, len(layers) * 1.55)
    ax.set_ylim(0, 4)
    ax.axis("off")
    ax.set_title("TEP Detector Defense-in-Depth — 8-stage chain with 27 supporting CUBs\nAll layers carry triple-kernel proofs (Verus + Coq 8.18 + Lean 4.10), zero placeholders",
                 fontsize=11, pad=20)
    fig.tight_layout()
    fig.savefig(OUT / "failsafe_defense_chain.pdf", bbox_inches="tight")
    fig.savefig(OUT / "failsafe_defense_chain.png", dpi=180, bbox_inches="tight")
    plt.close(fig)
    print("wrote failsafe_defense_chain.{pdf,png}")


if __name__ == "__main__":
    chart_60_runs()
    chart_verification_matrix()
    chart_sota()
    chart_layers()
    print(f"\nAll charts written to {OUT}")
