"""Shares from scan.jsonl (README.md verdict rule). Usage: python -I analyse.py SCAN_JSONL [RECHECK_JSON]
A host counts as answering h3 if the scan or the slow recheck (recheck.py) completed the handshake."""
import json, math, sys
from collections import Counter

def wilson(k, n, z=1.96):
    if n == 0: return (float("nan"),) * 2
    p = k / n; d = 1 + z * z / n
    c = (p + z * z / (2 * n)) / d; h = z * math.sqrt(p * (1 - p) / n + z * z / (4 * n * n)) / d
    return c - h, c + h

def flags(r):
    alt = "h3" in [t.split("=")[0].strip() for t in (r.get("alt_svc") or "").replace(";", ",").split(",")]
    rr = r.get("https_rr"); dnsh3 = isinstance(rr, list) and any("h3" in x.split("alpn=")[-1].split()[0] for x in rr if "alpn=" in x)
    return {"alt": alt, "dns": dnsh3, "quic": r.get("quic") == "h3",
            "cf": (r.get("server") or "").lower() == "cloudflare"}

rows = [json.loads(l) for l in open(sys.argv[1])]
re = json.load(open(sys.argv[2])) if len(sys.argv) > 2 else {}
for r in rows:
    if re.get(r.get("final")) == "h3": r["quic"] = "h3"
out = []
for name, sel in [("top100", lambda r: r["sample"] == "top" and r["rank"] <= 100),
                  ("top1000", lambda r: r["sample"] == "top"), ("tail", lambda r: r["sample"] == "tail")]:
    s = [r for r in rows if sel(r)]; ok = [r for r in s if r["ok"]]; n = len(ok)
    F = [flags(r) for r in ok]
    def line(key):
        k = sum(f[key] for f in F); lo, hi = wilson(k, n)
        return f"{key}: {k}/{n} = {100*k/n:.1f} % [{100*lo:.1f}, {100*hi:.1f}]"
    out.append(f"## {name}: {len(s)} domains, reachable {n} ({100*n/len(s):.1f} %)")
    out += ["- " + line(k) for k in ("quic", "alt", "dns", "cf")]
    combo = Counter((f["alt"], f["dns"], f["quic"]) for f in F)
    out.append("- (alt, dns, quic) counts: " + ", ".join(f"{k}: {v}" for k, v in sorted(combo.items(), reverse=True)))
    q = [f for f in F if f["quic"]]
    if q: out.append(f"- of h3-answering, on Cloudflare: {sum(f['cf'] for f in q)}/{len(q)} = {100*sum(f['cf'] for f in q)/len(q):.1f} %")
    cf = [f for f in F if f["cf"]]; ncf = [f for f in F if not f["cf"]]
    for lab, g in (("Cloudflare", cf), ("not Cloudflare", ncf)):
        if g: out.append(f"- h3 among {lab}: {sum(f['quic'] for f in g)}/{len(g)} = {100*sum(f['quic'] for f in g)/len(g):.1f} %")
    errs = Counter(r["quic"] for r in ok if r.get("quic") != "h3")
    out.append("- non-h3 quic results: " + ", ".join(f"{k} {v}" for k, v in errs.most_common(6)))
print("\n".join(out))
