"""
score.py — applies the pre-registered decision rule. Do not edit after baseline.

Reads filled tracker CSVs (one per wave) and prints the verdict.

Usage:
    python score.py --baseline wave-B1.csv wave-B2.csv --outcome wave-T3.csv wave-T4.csv

Rule (fixed before any data was collected):
  1. Per page, per wave: citations = rows where target_url_cited == Y.
  2. Baseline = mean of the two baseline waves. Outcome = mean of the final two waves.
  3. Change = outcome - baseline, per page.
  4. Per pair: diff = change(KEEP) - change(REMOVE).
       diff > 0  -> pair supports the hypothesis
       diff < 0  -> pair contradicts it
       diff == 0 -> tie, excluded
  5. One-sided exact sign test on non-tied pairs.
       fewer than 5 non-tied pairs  -> INCONCLUSIVE (floor effect)
       p <= 0.05                     -> SUPPORTS the hypothesis
       0.05 < p <= 0.10              -> DIRECTIONAL ONLY, not conclusive
       p > 0.10                      -> NO EVIDENCE of an effect
"""
import argparse, csv
from collections import defaultdict
from math import comb


def load(paths):
    waves = []
    for p in paths:
        c = defaultdict(int)
        meta = {}
        with open(p, newline="") as f:
            for r in csv.DictReader(f):
                meta[r["target_url"]] = (r["pair"], r["arm"])
                c[r["target_url"]] += r["target_url_cited"].strip().upper() in ("Y", "YES", "1", "TRUE")
        waves.append((c, meta))
    return waves


def mean(waves, url):
    return sum(w[0].get(url, 0) for w in waves) / len(waves)


def sign_p(wins, n):
    return sum(comb(n, k) for k in range(wins, n + 1)) / 2 ** n


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--baseline", nargs=2, required=True)
    ap.add_argument("--outcome", nargs=2, required=True)
    a = ap.parse_args()
    B, O = load(a.baseline), load(a.outcome)
    meta = {**B[0][1], **O[-1][1]}

    pairs = defaultdict(dict)
    for url, (pid, arm) in meta.items():
        pairs[pid][arm] = mean(O, url) - mean(B, url)

    wins = losses = ties = 0
    print(f"{'pair':<5}{'KEEP Δ':>9}{'REMOVE Δ':>10}{'diff':>8}  result")
    for pid in sorted(pairs):
        k, r = pairs[pid].get("KEEP", 0), pairs[pid].get("REMOVE", 0)
        d = k - r
        res = "supports" if d > 0 else "contradicts" if d < 0 else "tie"
        wins += d > 0; losses += d < 0; ties += d == 0
        print(f"{pid:<5}{k:>9.2f}{r:>10.2f}{d:>8.2f}  {res}")

    n = wins + losses
    print(f"\nnon-tied pairs: {n}  (supports {wins}, contradicts {losses}, ties {ties})")
    if n < 5:
        print("VERDICT: INCONCLUSIVE — too few non-tied pairs (floor effect).")
        return
    p = sign_p(wins, n)
    print(f"one-sided sign test p = {p:.4f}")
    if p <= 0.05:
        print("VERDICT: SUPPORTS the hypothesis that FAQPage schema contributes to AI citation.")
    elif p <= 0.10:
        print("VERDICT: DIRECTIONAL ONLY — consistent with an effect, not conclusive.")
    else:
        print("VERDICT: NO EVIDENCE of an effect at this sample size.")
    print("\nPublish this output as-is, whatever it says.")


if __name__ == "__main__":
    main()
