"""Audit check 1: the purchase gate at the deployed cell.

Reproduces decision.json's "random side, swap charged" row with the repository's own
prime.py (exact chains + wallet_mc), then measures how far the gate verdict is from zero
in Monte Carlo error and at which input value it flips. All wallet runs are 5,000 paths.

Run from the research checkout root, one process:
    cd /root/Projects/trading-framework && python3 /tmp/arena-prime-audit/candidate-2/c2_gate.py
"""
import json
import sys
import time

import numpy as np

sys.path.insert(0, "/root/Projects/trading-framework")
from src.notebooks.reports.topics.prime_academy.modules import prime as PA  # noqa: E402

OUT = "/tmp/arena-prime-audit/candidate-2/c2_gate.json"
DEC = json.load(open("/root/Projects/trading-framework/src/notebooks/reports/topics/prime_academy/paper/decision.json"))
SPLIT, B, FEE, W0 = 0.70, 3000.0, 38.0, 1000.0
T3 = PA.Tier(B, FEE, 51.0)
STOP = DEC["stop"]                       # 34.79 pips
WAIT = DEC["wait"]                       # 7 trades
H = DEC["horizon"]                       # 541 trades
SEEDS = [1, 2, 3, 4]
N = 5000
G_COIN = DEC["scenarios"]["random side, swap charged"]["cost"]       # 3.35%
SWAP_COIN = DEC["side_share"]["coin"]                                # +0.48% of risk
SWAP_SHORT = DEC["side_share"]["short"]                              # -0.38%
G_CS = PA.cost_share(STOP)                                           # 2.87%
res = {}


def pick(g, wait=WAIT):
    rows = PA.funded_line_search(g, lo=0.006, hi=0.020, step=0.00025, wait=wait)
    plat = PA.plateau(rows)
    pk = min(plat, key=lambda r: (r["med_first_pay"], -r["e_W"]))
    return pk, plat, rows


def gate(g, rf, honour=0.8, ra=0.03, wait=WAIT, clip_dn=True, clip_up=True, seeds=SEEDS, n=N, horizon=H):
    """Mean and SD over seeds of the wallet's expected log growth, plus ruin."""
    gs, ruins = [], []
    for s in seeds:
        w = PA.wallet_mc(T3, ra, g * ra, SPLIT, honour, W0, horizon_days=horizon, n=n, seed=s, rr=1.0,
                         wait=wait, funded_risk=rf, funded_cost=g * rf, clip_up=clip_up, clip_dn=clip_dn)
        gs.append(w["e_log_growth"]); ruins.append(w["p_ruin"])
    return float(np.mean(gs)), float(np.std(gs, ddof=1)), float(np.mean(ruins)), gs


def chains(g, rf, ra=0.03, wait=WAIT, clip_dn=True):
    e = PA.eval_chain(ra, g * ra, rr=1.0, clip_up=True, clip_dn=clip_dn)
    f = PA.funded_chain(rf, g * rf, PA.payout_threshold(rf, 1.0, B, SPLIT), rr=1.0, clip_dn=clip_dn, wait=wait)
    cash = SPLIT * B * e["p_pass"] * f["e_W"]
    return dict(p_pass=e["p_pass"], e_trades=e["e_trades"], p_any=f["p_any"], e_W=f["e_W"], e_life=f["e_life"],
                med_first_pay=f["med_first_pay"], cash_fee=cash / FEE, breakeven=FEE / cash)


t0 = time.time()
# ---- 1. reproduce the published row -------------------------------------------------------
pk, plat, rows = pick(G_COIN)
pub = DEC["scenarios"]["random side, swap charged"]
print(f"[1] reproduce: pick {pk['risk']:.5f} (published {pub['pick']['risk']:.5f}), p_any {pk['p_any']:.4f} "
      f"(published {pub['pick']['p_any']:.4f}), plateau {plat[0]['risk']:.5f}..{plat[-1]['risk']:.5f} "
      f"(published {pub['plateau'][0]:.5f}..{pub['plateau'][1]:.5f})")
ch = chains(G_COIN, pk["risk"])
print(f"    chains: p_pass {ch['p_pass']:.4f} (pub {pub['gate']['p_pass']:.4f}), cash/fee {ch['cash_fee']:.3f} "
      f"(pub {pub['gate']['cash_fee']:.3f}), breakeven {ch['breakeven']:.3f} (pub {pub['gate']['breakeven']:.3f})")
res["reproduce"] = dict(pick=pk["risk"], plateau=[plat[0]["risk"], plat[-1]["risk"]], **ch)

# the pick rule inside the plateau: med_first_pay and e_W along the plateau
res["plateau_rows"] = [dict(risk=r["risk"], p_any=r["p_any"], med_first_pay=r["med_first_pay"], e_W=r["e_W"]) for r in plat]
print("    plateau rows (risk, p_any, med_first_pay, e_W):")
for r in plat:
    print(f"      {r['risk']:.5f}  {r['p_any']:.4f}  {r['med_first_pay']:3d}  {r['e_W']:.5f}")

# ---- 2. the gate's Monte Carlo error at the published cell ------------------------------------
g80, sd80, ruin, gs = gate(G_COIN, pk["risk"], 0.8)
g100, sd100, _, _ = gate(G_COIN, pk["risk"], 1.0)
print(f"[2] gate at 3.35%: g_80 mean {g80:+.4f} sd {sd80:.4f} over {len(SEEDS)} seeds x {N} paths ({[round(x, 4) for x in gs]}); "
      f"published +0.0132 at 10,000 paths. g_100 {g100:+.4f} sd {sd100:.4f} (pub +0.206). ruin {ruin:.4f}")
res["gate_published_cell"] = dict(g80=g80, sd80=sd80, g80_seeds=gs, g100=g100, sd100=sd100, ruin=ruin)

# ---- 3. flip in the cost share, funded pick re-searched per cost -----------------------------
print("[3] cost-share scan (pick re-searched at each cost):")
scan = []
for g in [0.0249, 0.0287, 0.0300, 0.0320, 0.0335, 0.0345, 0.0355, 0.0365, 0.0380, 0.0400, 0.0450]:
    pk_g, plat_g, _ = pick(g)
    m, sd, ru, _ = gate(g, pk_g["risk"], 0.8)
    c = chains(g, pk_g["risk"])
    scan.append(dict(g=g, pick=pk_g["risk"], p_any=pk_g["p_any"], g80=m, sd=sd, ruin=ru, cash_fee=c["cash_fee"], p_pass=c["p_pass"]))
    print(f"    cost {g:.4f}: pick {pk_g['risk']:.5f} p_any {pk_g['p_any']:.4f} pass {c['p_pass']:.4f} cash/fee {c['cash_fee']:.3f} "
          f"g_80 {m:+.4f} (sd {sd:.4f}) ruin {ru:.4f}")
res["cost_scan"] = scan
# linear root of g80 in cost
xs = np.array([r["g"] for r in scan]); ys = np.array([r["g80"] for r in scan])
i = np.where(np.diff(np.sign(ys)) != 0)[0]
root = None
if len(i):
    j = i[0]; root = float(xs[j] - ys[j] * (xs[j + 1] - xs[j]) / (ys[j + 1] - ys[j]))
    print(f"    g_80 crosses zero at a cost share of about {root:.4f} of the risk "
          f"= {(root - G_COIN) * STOP:.3f} extra pips a round trip over the 3.35% row")
res["cost_root"] = root

# ---- 4. flip in the honour rate at the published cell -----------------------------------------
print("[4] honour scan at 3.35%, pick 1.575%:")
hs = []
for h in [0.70, 0.75, 0.78, 0.80, 0.82, 0.85, 0.90, 1.00]:
    m, sd, ru, _ = gate(G_COIN, pk["risk"], h)
    hs.append(dict(h=h, g80=m, sd=sd)); print(f"    honour {h:.2f}: g {m:+.4f} (sd {sd:.4f})")
res["honour_scan"] = hs
xs = np.array([r["h"] for r in hs]); ys = np.array([r["g80"] for r in hs])
i = np.where(np.diff(np.sign(ys)) != 0)[0]
hroot = None
if len(i):
    j = i[0]; hroot = float(xs[j] - ys[j] * (xs[j + 1] - xs[j]) / (ys[j + 1] - ys[j]))
    print(f"    growth crosses zero at honour about {hroot:.3f}")
res["honour_root"] = hroot

# ---- 5. the clock in trades (pace reading) ----------------------------------------------------
print("[5] payout clock in trades (14 calendar days / pace), pick re-searched, horizon kept at 541 trades:")
ws = []
for wt in [5, 6, 7, 8, 9, 10, 12, 14]:
    pk_w, _, _ = pick(G_COIN, wait=wt)
    m, sd, ru, _ = gate(G_COIN, pk_w["risk"], 0.8, wait=wt)
    ws.append(dict(wait=wt, pick=pk_w["risk"], p_any=pk_w["p_any"], g80=m, sd=sd))
    print(f"    wait {wt:2d} trades (pace {14 / wt:.2f} d/trade): pick {pk_w['risk']:.5f} p_any {pk_w['p_any']:.4f} g_80 {m:+.4f} (sd {sd:.4f})")
res["wait_scan"] = ws

# ---- 6. the 35% cap not applied in the assessment: 4% risk -----------------------------------
print("[6] assessment risk 4% (cap not applied), funded pick unchanged:")
for ra in [0.03, 0.035, 0.04, 0.0448]:
    c = chains(G_COIN, pk["risk"], ra=ra)
    m, sd, ru, _ = gate(G_COIN, pk["risk"], 0.8, ra=ra)
    print(f"    assess {ra:.4f}: pass {c['p_pass']:.4f} trades {c['e_trades']:.2f} cash/fee {c['cash_fee']:.3f} g_80 {m:+.4f} (sd {sd:.4f}) ruin {ru:.4f}")
    res.setdefault("assess_scan", []).append(dict(ra=ra, g80=m, sd=sd, ruin=ru, **c))

# ---- 7. the floor read on review (no tick clip) -----------------------------------------------
print("[7] floor enforced on review (clip_dn False) against on the tick:")
for cd in (True, False):
    c = chains(G_COIN, pk["risk"], clip_dn=cd)
    m, sd, ru, _ = gate(G_COIN, pk["risk"], 0.8, clip_dn=cd)
    print(f"    clip_dn {cd}: pass {c['p_pass']:.4f} p_any {c['p_any']:.4f} e_W {c['e_W']:.4f} cash/fee {c['cash_fee']:.3f} g_80 {m:+.4f} (sd {sd:.4f})")
    res.setdefault("floor_scan", []).append(dict(clip_dn=cd, g80=m, sd=sd, **c))

# ---- 8. the side policy: always short (credited swap) ---------------------------------------
g_short = G_CS + SWAP_SHORT
pk_s, _, _ = pick(g_short)
m, sd, ru, _ = gate(g_short, pk_s["risk"], 0.8)
c = chains(g_short, pk_s["risk"])
print(f"[8] always short, cost {g_short:.4f}: pick {pk_s['risk']:.5f} pass {c['p_pass']:.4f} p_any {c['p_any']:.4f} cash/fee {c['cash_fee']:.3f} g_80 {m:+.4f} (sd {sd:.4f})")
res["short_side"] = dict(g=g_short, pick=pk_s["risk"], g80=m, sd=sd, **c)

# ---- 9. aside rate and spread: the gate boundary ----------------------------------------------
# cost(s, A) = (0.5 + s)/stop + swap_coin + A (0.5 + s)/stop ; the gate closes where cost > root
if root:
    print(f"[9] with g_80 = 0 at a cost share of {root:.4f}: the largest step-aside rate per trade that keeps the gate open, by spread:")
    tab = []
    for s in [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]:
        base = (0.5 + s) / STOP + SWAP_COIN
        a_max = (root - base) / ((0.5 + s) / STOP)
        tab.append(dict(spread=s, base_cost=base, a_max=a_max))
        print(f"    spread {s:.1f} pip: base cost {base:.4f}, max asides/trade {a_max:+.3f} (measured 1.33 all-currency; EUR+USD share of events {(974 + 206) / 2393:.2f} -> about {1.33 * (974 + 206) / 2393:.2f})")
    res["aside_boundary"] = tab

json.dump(res, open(OUT, "w"), indent=1, default=float)
print(f"done in {time.time() - t0:.0f} s -> {OUT}")
