"""Analyze + plot exp (b): realized APC and latency vs GPU KV capacity (the knee)."""
import json
import statistics
import sys
from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

R = Path(sys.argv[1] if len(sys.argv) > 1 else "v2/exp_b_capacity_knee/results")
FIG = Path(sys.argv[2] if len(sys.argv) > 2 else "v2/figs/exp_b_capacity_knee.png")
BLOCK_BYTES = 16 * 98304  # 1.573 MB / block


def pct(v, q):
    v = sorted(v)
    return v[min(int(q * len(v)), len(v) - 1)] if v else 0.0


rows = []
for mf in sorted(R.glob("metrics_blk*.jsonl"), key=lambda p: int(p.stem.split("blk")[1])):
    blk = int(mf.stem.split("blk")[1])
    gb = blk * BLOCK_BYTES / 1e9
    recs = [json.loads(l) for l in open(mf)]
    ok = [r for r in recs if not r.get("error")]
    ttft = [r["ttft_s"] for r in ok if r.get("ttft_s")]
    e2e = [r["latency_s"] for r in ok if r.get("latency_s")]
    m0 = json.load(open(R / f"m0_blk{blk}.json"))
    m1 = json.load(open(R / f"m1_blk{blk}.json"))
    dq = m1["gpu_queries"] - m0["gpu_queries"]
    dh = m1["gpu_hits"] - m0["gpu_hits"]
    apc = dh / dq if dq > 0 else 0.0
    rows.append({
        "blocks": blk, "gb": gb,
        "apc": apc,
        "completion": len(ok) / len(recs) if recs else 0,
        "n_ok": len(ok), "n": len(recs),
        "ttft_p50": pct(ttft, .5), "ttft_p90": pct(ttft, .9),
        "e2e_p50": pct(e2e, .5), "e2e_p90": pct(e2e, .9),
    })

print(f"{'GB':>6} {'blocks':>7} {'APC':>7} {'compl':>6} {'TTFTp50':>8} {'TTFTp90':>8} {'E2Ep90':>8}")
for r in rows:
    print(f"{r['gb']:>6.1f} {r['blocks']:>7} {r['apc']:>6.1%} {r['completion']:>6.0%} "
          f"{r['ttft_p50']:>8.3f} {r['ttft_p90']:>8.3f} {r['e2e_p90']:>8.3f}")
json.dump(rows, open(R / "summary.json", "w"), indent=2)

if rows:
    gb = [r["gb"] for r in rows]
    fig, ax1 = plt.subplots(figsize=(7.4, 5.0))
    ax1.plot(gb, [r["apc"] * 100 for r in rows], "o-", color="#2ca02c",
             linewidth=2.2, markersize=8, label="Realized APC")
    ax1.set_xlabel("GPU KV-cache capacity (GB)")
    ax1.set_ylabel("Realized APC (%)", color="#2ca02c")
    ax1.tick_params(axis="y", labelcolor="#2ca02c")
    ax1.set_ylim(0, 100)
    ax1.grid(True, alpha=0.3)

    ax2 = ax1.twinx()
    ax2.plot(gb, [r["ttft_p90"] for r in rows], "s--", color="#d62728",
             linewidth=2, markersize=7, label="TTFT p90")
    ax2.set_ylabel("TTFT p90 (s)", color="#d62728")
    ax2.tick_params(axis="y", labelcolor="#d62728")

    ax1.set_title("APC and latency saturate at small GPU KV capacity\n"
                  "Qwen3-Coder-30B-A3B, 1xH20, agentic trace replay")
    fig.tight_layout()
    FIG.parent.mkdir(parents=True, exist_ok=True)
    fig.savefig(FIG, dpi=140)
    print("wrote", FIG)
