"""
SNIN Emission Paper Pilot — runner for P/N test vectors (FROZEN v0.4).
Usage: python3 run_tests.py   (must run from the package directory)
Prints PASS/FAIL per assertion. Exit code 0 only if all pass.
"""
import json
import emission as E

V = json.load(open("test_vectors.json"))
fix = V["fixtures"]
exp = V["expected_net_micro"]
failures = []

# 1) net balance per fixture — pure calculation (simulate=True: fixtures model
#    real events to test the FORMULA; storage isolation tested separately below)
nets = {}
for name, fx in fix.items():
    nets[name] = E.net_balance(fx["rows"], fx["actor"], simulate=True)

# 2) P1 > max(R1..R3)
p1 = nets["P1_corrective"]
red_max = max(nets[k] for k in ("R1_copycat_digest", "R2_plausible_incorrect", "R3_self_circle"))
if p1 > red_max:
    print(f"PASS  P1({p1}) > max(R1..R3)({red_max})  [positive control earns distinguishably]")
else:
    failures.append(f"P1={p1} not > red_max={red_max}")

# 3) expected nets
for name, want in exp.items():
    got = nets[name]
    if got == want:
        print(f"PASS  {name}: net={got} == expected {want}")
    else:
        failures.append(f"{name}: net={got} != expected {want}")

# 4) fixture isolation: is_fixture=true => emitted 0 even with huge amount
iso = E.quoted_reward({"is_fixture": True, "emission_class": "verify_accept", "amount_micro": 10**12})
if iso == {"balance": 0, "rating": 0}:
    print("PASS  fixture isolation: is_fixture=true => emitted_amount=0")
else:
    failures.append(f"fixture isolation broken: {iso}")

# presence and task_receipt never emit
for cls in ("presence", "task_receipt"):
    q = E.quoted_reward({"emission_class": cls, "amount_micro": 10**9})
    if q == {"balance": 0, "rating": 0}:
        print(f"PASS  {cls}: emitted_amount=0 (telemetry/object only)")
    else:
        failures.append(f"{cls} emitted: {q}")

# excluded classes never emit
for cls in ("copycat", "self_circle", "rubber_stamp", "mutual_sleep_digest", "entropy"):
    q = E.quoted_reward({"emission_class": cls, "amount_micro": 10**9})
    if q == {"balance": 0, "rating": 0}:
        print(f"PASS  excluded {cls}: 0")
    else:
        failures.append(f"excluded {cls} emitted: {q}")

# 5) double reversal on one credit raises
try:
    rows = [
        {"seq": 1, "actor": "A", "emission_class": "verify_accept", "amount_micro": 100, "outcome": "accepted"},
        {"seq": 2, "actor": "A", "reverses_event_id": 1, "effect": "rating_adjustment", "amount_micro": 100, "basis": "fraud"},
        {"seq": 3, "actor": "A", "reverses_event_id": 1, "effect": "rating_adjustment", "amount_micro": 100, "basis": "fraud"},
    ]
    E.derived_rating(rows)
    failures.append("double reversal did NOT raise")
except ValueError:
    print("PASS  double reversal on one credit raises ValueError (UNIQUE(reverses_event_id, effect))")

# 6) conservation on a synthetic set
cons = E.conservation([
    {"seq": 1, "actor": "A", "emission_class": "verify_accept", "amount_micro": 100, "outcome": "accepted"},
    {"seq": 2, "actor": "B", "emission_class": "verify_reject", "amount_micro": 100, "outcome": "rejected"},
], stakes_total=200)
if cons["ok"] and cons["payouts"] == 200:
    print("PASS  conservation: sum(payouts)+carry == sum(stakes)*(1-edge)")
else:
    failures.append(f"conservation broken: {cons}")

print("-" * 60)
if failures:
    print("FAILURES:", len(failures))
    for f in failures:
        print("  FAIL", f)
    raise SystemExit(1)
print("ALL TESTS PASSED")
