"""The purchase gate (section 25) under its uncertain inputs. wallet_mc, 5,000 paths a run, runs in
sequence in this one process. Common random numbers: every variant reuses seed 5 (the notebook's
SEED), so differences between variants carry little sampling noise; seed 6 is an independent
replicate of the deployed cell.

  1. the deployed cell: mean log growth, per-path SE, two seeds
  2. the gate against the cost share (funded risk re-picked at each cost), zero crossing,
     read as spread, step-asides, extra pips a trade, and win-rate shortfall
  3. the gate against the honour rate
  4. the gate against the payout clock in trades, and against the horizon
  5. a refusal that ends the account instead of only forfeiting the request
"""
import json
import time

import numpy as np

from common import PA, T3, SPLIT, G_COIN, G_SPREAD, STOP0, cell, pick, wallet

t0 = time.time()
N = 5000
out = {}


def lg(w):
    x = np.log(np.maximum(w["paths"]["final"], 1.0) / 1000.0)
    return float(x.mean()), float(x.std(ddof=1) / np.sqrt(len(x)))


RF0 = 0.01575
# 1. deployed cell
for seed in (5, 6):
    w = wallet(G_COIN, 7, RF0, n=N, seed=seed)
    m, se = lg(w)
    print(f"deployed, seed {seed}: E[log g] {m:+.4f} +/- {se:.4f} (per-path SE), ruin {w['p_ruin']:.2%}, "
          f"any cash {w['p_any_cash']:.1%}, mean final ${w['mean_final']:.0f}")
    out[f"deployed_seed{seed}"] = dict(m=m, se=se, ruin=w["p_ruin"], mean_final=w["mean_final"])

# 2. cost share
out["cost"] = []
for dg in (-0.004, -0.002, 0.0, 0.0005, 0.001, 0.0015, 0.002, 0.003, 0.005):
    g = G_COIN + dg
    rf = pick(g, 7)[0]["risk"]
    c = cell(g, 7, rf=rf)
    m, se = lg(wallet(g, 7, rf, n=N, seed=5))
    out["cost"].append(dict(dg=dg, g=g, rf=rf, cash_fee=c["cash_fee"], G=c["G"], m=m, se=se))
    print(f"cost {g:.3%} (+{dg:+.2%}): pick {rf:.3%} cash/fee {c['cash_fee']:.3f} G ${c['G']:+.1f} E[log g] {m:+.4f} +/- {se:.4f}  [{time.time()-t0:.0f}s]")
cs = out["cost"]
xs = np.array([r["g"] for r in cs]); ys = np.array([r["m"] for r in cs])
i = int(np.flatnonzero((ys[:-1] > 0) & (ys[1:] <= 0))[0])
gstar = float(xs[i] + (xs[i + 1] - xs[i]) * ys[i] / (ys[i] - ys[i + 1]))
dstar = gstar - G_COIN
print(f"zero crossing at cost share {gstar:.3%}, {dstar:+.3%} over the deployed {G_COIN:.3%}")
print(f"  = spread {0.5 + dstar * STOP0:.2f} pips (assumed 0.5); step-asides {dstar / G_SPREAD:.3f} a trade (measured 1.33); "
      f"extra {dstar * STOP0:.2f} pips a trade (slippage, swap); win-rate shortfall {dstar / 2:.3%} points")
out["gstar"] = gstar

# 3. honour rate
out["honour"] = []
for h in (0.70, 0.75, 0.78, 0.80, 0.82, 0.85, 0.90, 1.0):
    m, se = lg(wallet(G_COIN, 7, RF0, n=N, seed=5, h=h))
    out["honour"].append(dict(h=h, m=m, se=se))
    print(f"honour {h:.0%}: E[log g] {m:+.4f} +/- {se:.4f}")

# 4. clock and horizon
out["clock"] = []
for wait in (6, 7, 8, 10, 14):
    rf = pick(G_COIN, wait)[0]["risk"]
    m, se = lg(wallet(G_COIN, wait, rf, n=N, seed=5))
    out["clock"].append(dict(wait=wait, rf=rf, m=m, se=se))
    print(f"clock {wait} trades (pick {rf:.3%}): E[log g] {m:+.4f} +/- {se:.4f}")
out["horizon"] = []
for yrs in (1, 2, 3, 4, 5):
    H = int(round(yrs * 365 / 2.02508032004559))
    m, se = lg(wallet(G_COIN, 7, RF0, n=N, seed=5, horizon=H))
    out["horizon"].append(dict(years=yrs, H=H, m=m, se=se))
    print(f"horizon {yrs} y ({H} trades): E[log g] {m:+.4f} +/- {se:.4f}")
m14, se14 = lg(wallet(G_COIN, 14, 0.016, n=N, seed=5, horizon=500))
print(f"the previous configuration (14-trade clock, pick 1.6%, 500 trades): E[log g] {m14:+.4f} +/- {se14:.4f}")
m7_500, _ = lg(wallet(G_COIN, 7, RF0, n=N, seed=5, horizon=500))
print(f"7-trade clock at 500 trades: {m7_500:+.4f}; 14-trade clock at 541 trades: "
      f"{lg(wallet(G_COIN, 14, 0.016, n=N, seed=5, horizon=541))[0]:+.4f}")


# 5. a refusal ends the account (General Terms 23.1 and clause 16 allow it); a copy of wallet_mc's
#    payout block with that one change, everything else identical
def wallet_terminate(g, wait, rf, h, n=N, seed=5, horizon=541, ra=0.03):
    rng = np.random.default_rng(seed)
    fee, B, min_gross = T3.fee, T3.bankroll, 100.0 / SPLIT / T3.bankroll
    w = np.full(n, 1000.0); ruined = np.zeros(n, bool); state = np.full(n, -1, np.int8)
    eq = np.zeros(n); since = np.zeros(n); traded = np.zeros(n); big = np.zeros(n)
    for d in range(horizon):
        idle = (state == -1) & ~ruined
        buy = idle & (w >= fee - PA.TOL)
        w = np.where(buy, w - fee, w); state = np.where(buy, 0, state)
        eq = np.where(buy, 0.0, eq); since = np.where(buy, 0, since); traded = np.where(buy, 0, traded); big = np.where(buy, 0.0, big)
        ruined |= idle & ~buy
        act = (state >= 0) & ~ruined
        prev = eq.copy()
        u = rng.random(n)
        st_a, win_a, a_a = PA._steps_clipped(rng, n, ra, g * ra, 1.0, eq, True, True, u=u)
        st_f, win_f, a_f = PA._steps_clipped(rng, n, rf, g * rf, 1.0, eq, False, True, u=u)
        fund = state == 1
        st = np.where(fund, st_f, st_a); win = np.where(fund, win_f, win_a); wsz = np.where(fund, a_f, a_a)
        eq = np.where(act, eq + st, eq); since += act; traded += act
        big = np.where(act & win & (wsz > big), wsz, big)
        dead = act & (((prev - eq) > PA.DAILY * (1.0 + prev)) | (eq <= -PA.MAXDD))
        state = np.where(dead, -1, state)
        promoted = act & (state == 0) & (eq >= PA.TARGET)
        state = np.where(promoted, 1, state); eq = np.where(promoted, 0.0, eq)
        since = np.where(promoted, 0, since); traded = np.where(promoted, 0, traded); big = np.where(promoted, 0.0, big)
        can = (state == 1) & ~ruined & (since >= wait) & (traded >= PA.MIN_DAYS) & (eq >= min_gross) & (big <= PA.DIST_CAP * eq)
        honoured = can & (rng.random(n) < h)
        w = w + np.where(honoured, SPLIT * eq * B, 0.0)
        state = np.where(can & ~honoured, -1, state)            # the one change: a refusal ends the account
        eq = np.where(can, 0.0, eq); since = np.where(can, 0, since); big = np.where(can, 0.0, big)
    x = np.log(np.maximum(w, 1.0) / 1000.0)
    return float(x.mean()), float(x.std(ddof=1) / np.sqrt(n)), float(ruined.mean())


m_same, _ = lg(wallet(G_COIN, 7, RF0, n=N, seed=5, h=0.8))
m_t, se_t, ru_t = wallet_terminate(G_COIN, 7, RF0, 0.8)
m_t1, _, _ = wallet_terminate(G_COIN, 7, RF0, 1.0)
print(f"refusal ends the account, honour 80%: E[log g] {m_t:+.4f} +/- {se_t:.4f}, ruin {ru_t:.2%} "
      f"(per-request refusal, same seed: {m_same:+.4f}; check at 100% honoured, should equal wallet_mc: {m_t1:+.4f})")
for h in (0.85, 0.9, 0.95):
    print(f"  refusal ends the account, honour {h:.0%}: E[log g] {wallet_terminate(G_COIN, 7, RF0, h)[0]:+.4f}")
m_ref, _ = lg(wallet(G_COIN, 7, RF0, n=N, seed=5, h=1.0))
print(f"  wallet_mc at 100% honoured, seed 5: {m_ref:+.4f}")
out["terminate"] = dict(m=m_t, se=se_t, ruin=ru_t)
json.dump(out, open("/tmp/arena-prime-audit/candidate-1/out_s02.json", "w"), default=float, indent=1)
print(f"done {time.time() - t0:.0f}s")
