#!/usr/bin/env python3
"""独立复算：纯标准库实现，不用 scipy、不用 numpy，直接从 eval_raw.json 重算全部头条数字。

与 05_analyze.py 的实现路径完全独立：
  * 精确 Wilcoxon 符号秩 p 值由 2^12=4096 种符号翻转的全枚举得到，不调用任何统计库；
  * 中位数、rank-biserial、计数全部自己算。
两条路径必须一致，否则 audit_delivery.py 失败。
"""
from __future__ import annotations

import json
from itertools import product
from pathlib import Path

PKG = Path(__file__).resolve().parents[2]
RAW = json.loads((PKG / "work/results/eval_raw.json").read_text(encoding="utf-8"))
SEEDS = [str(s) for s in RAW["eval_seeds"]]


def median(v):
    w = sorted(v)
    n = len(w)
    return w[n // 2] if n % 2 else (w[n // 2 - 1] + w[n // 2]) / 2.0


def series(block, arm, key):
    return [float(block[arm][s][key]) for s in SEEDS]


def exact_wilcoxon(d):
    """精确双侧 Wilcoxon 符号秩检验，全枚举 2^n 种符号分配。"""
    n = len(d)
    order = sorted(range(n), key=lambda i: abs(d[i]))
    ranks = [0.0] * n
    for pos, i in enumerate(order):
        ranks[i] = pos + 1.0
    wp = sum(ranks[i] for i in range(n) if d[i] > 0)
    wn = sum(ranks[i] for i in range(n) if d[i] < 0)
    t_obs = min(wp, wn)
    total, le = 0, 0
    for signs in product((0, 1), repeat=n):
        total += 1
        s = sum(r for r, b in zip(ranks, signs) if b)
        if s <= t_obs + 1e-12:
            le += 1
    p = min(1.0, 2.0 * le / total)
    rb = (wp - wn) / (wp + wn) if (wp + wn) else 0.0
    return t_obs, p, rb, wp, wn


def paired(better, worse, label, metric):
    d = [w - b for b, w in zip(better, worse)]
    t, p, rb, wp, wn = exact_wilcoxon(d)
    return {"comparison": label, "metric": metric, "n_seeds": len(d),
            "n_seeds_better": sum(1 for v in d if v > 0),
            "median_paired_diff": median(d), "mean_paired_diff": sum(d) / len(d),
            "wilcoxon_statistic": t, "wilcoxon_p_two_sided_exact": p, "rank_biserial": rb}


def main() -> int:
    real = RAW["real"]
    nullv = series(real, "null_no_intervention", "P_end")
    tests = {}
    tests["H1_primary_rl_vs_extremity_P_end"] = paired(
        series(real, "offline_rl_fqi", "P_end"), series(real, "extremity_top_b", "P_end"),
        "offline_rl_fqi 对 extremity_top_b（主对照）", "P_end")
    tests["H1_secondary_rl_vs_extremity_P_auc"] = paired(
        series(real, "offline_rl_fqi", "P_auc"), series(real, "extremity_top_b", "P_auc"),
        "offline_rl_fqi 对 extremity_top_b（次要终点 AUC）", "P_auc")
    for a in ["random_budget_matched", "degree_top_b", "extremity_top_b", "offline_rl_fqi"]:
        tests[f"H2_sanity_{a}_vs_null_P_end"] = paired(
            series(real, a, "P_end"), nullv, f"{a} 对零模型", "P_end")
    tests["H3_ruler_positive_double_vs_single_budget"] = paired(
        series(real, "extremity_double_budget", "P_end"),
        series(real, "extremity_top_b", "P_end"), "预算翻倍 对 单倍", "P_end")
    tests["H4_ruler_negative_random_a_vs_b"] = paired(
        series(real, "random_variant_a", "P_end"),
        series(real, "random_variant_b", "P_end"), "两个随机变体互比", "P_end")

    per_arm = {}
    for a in real:
        pe = series(real, a, "P_end")
        per_arm[a] = {
            "P_end_median": median(pe),
            "reduction_vs_null_median": median([n - p for n, p in zip(nullv, pe)]),
            "relative_reduction_vs_null_median_pct":
                median([(n - p) / n * 100 for n, p in zip(nullv, pe)]),
            "spend_max": max(int(real[a][s]["spend"]) for s in SEEDS),
            "budget_declared": int(real[a][SEEDS[0]]["budget"]),
        }
        per_arm[a]["budget_respected"] = per_arm[a]["spend_max"] <= per_arm[a]["budget_declared"]
    out = {"implementation": "纯标准库全枚举，不依赖 scipy/numpy",
           "tests": tests, "per_arm": per_arm,
           "all_budgets_respected": all(v["budget_respected"] for v in per_arm.values())}
    (PKG / "work/results/recheck.json").write_text(
        json.dumps(out, ensure_ascii=False, indent=1), encoding="utf-8")
    print(json.dumps({k: {kk: v[kk] for kk in ("n_seeds_better", "median_paired_diff",
                                               "wilcoxon_p_two_sided_exact", "rank_biserial")}
                      for k, v in tests.items()}, ensure_ascii=False, indent=1))
    return 0


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