"""A copy of prime.wallet_mc (modules/prime.py:600-702) with one added switch, `refusal`, and nothing else changed:
  "reset"  what the repo does: a refused request still sets equity to zero and restarts the clock (profit lost, account lives)
  "keep"   a refused request leaves equity and the clock alone (the trader may ask again after the next trade)
  "close"  a refused request ends the account (profit lost, account gone)
Also returns the count of purchases per path so the terminal value of an open account can be priced."""
import numpy as np
from pa_imp import PA
from modules import hedge as HG
TOL=PA.TOL
def wallet_var(tier,risk,cost,split,p_paid,wallet0,horizon_days=500,n=5000,seed=13,rr=1.0,funded_risk=None,funded_cost=None,
               clip_up=True,clip_dn=True,wait=PA.WAIT,refusal="reset",mark_open=False,qkill=0.0,wait_dist=None):
    rng=np.random.default_rng(seed); fee=tier.fee; B=tier.bankroll
    min_gross=100.0/split/B
    risk_f=risk if funded_risk is None else funded_risk; cost_f=cost if funded_cost is None else funded_cost
    w=np.full(n,float(wallet0)); 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)
    purchases=np.zeros(n)
    wrng=np.random.default_rng(seed+999)
    def draw(k): return wrng.choice(wait_dist[0],size=k,p=wait_dist[1]).astype(float)
    waitv=np.full(n,float(wait)) if wait_dist is None else draw(n)
    for d in range(horizon_days):
        idle=(state==-1)&~ruined
        buy=idle&(w>=fee-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)
        purchases+=buy
        ruined|=idle&~buy
        act=(state>=0)&~ruined
        if not act.any() and ruined.all(): break
        prev=eq.copy(); u=rng.random(n)
        st_a,win_a,a_a=PA._steps_clipped(rng,n,risk,cost,rr,eq,clip_up,clip_dn,u=u)
        st_f,win_f,a_f=PA._steps_clipped(rng,n,risk_f,cost_f,rr,eq,False,clip_dn,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))
        if qkill>0: dead|=act&(state==0)&~win&(rng.random(n)<qkill)   # strict daily rule: a stop-out after an up-day boundary kills the assessment
        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>=waitv)&(traded>=PA.MIN_DAYS)&(eq>=min_gross)&(big<=PA.DIST_CAP*eq))
        ok=rng.random(n)<p_paid
        honoured=can&ok
        w=w+np.where(honoured,split*eq*B,0.0)
        if refusal=="reset":
            reset=can
        elif refusal=="keep":
            reset=honoured
        else:
            reset=honoured
            state=np.where(can&~ok,-1,state)
        eq=np.where(reset,0.0,eq); since=np.where(reset,0,since); big=np.where(reset,0.0,big)
        if wait_dist is not None:
            redraw=reset|promoted
            waitv=np.where(redraw,draw(n),waitv)
    return w,ruined,purchases
def glog(w,W0): return float(np.mean(np.log(np.maximum(w,1.0)/W0))), float(np.std(np.log(np.maximum(w,1.0)/W0),ddof=1)/np.sqrt(len(w)))
