"""
KALSHIBOT SMART LOOP — Trade-count-driven iteration trigger
============================================================
Replaces the fixed `timeout /t 1800` in run_loop.bat.

Reads experiment_state.json (written by iterate.py after each restart)
to know EXACTLY when this experiment started and what the trade baseline
was. This gives an accurate count of trades from THIS experiment only.

TRIGGER CONDITIONS (any one fires the next iteration):
  1. PRIMARY  : MIN_NEW_TRADES new trades seen AND MIN_WAIT_SECS elapsed
  2. EARLY    : 5+ new trades AND a very strong signal (WR >= STRONG_SIGNAL_WR or <= inverse)
  3. HARD CAP : MAX_WAIT_SECS elapsed regardless (safety net for dead markets)
"""
import json, os, time, datetime

ANALYTICS_PATH        = r"C:\kalshibot\Automated\trade_analytics.json"
BOT_STATE_PATH        = r"C:\kalshibot\Automated\bot_state.json"
EXPERIMENT_STATE_PATH = r"C:\kalshibot\Automated\tracker\experiment_state.json"

# ── Trigger config ─────────────────────────────────────────────────────────────
MIN_NEW_TRADES   = 5     # Need at least this many new trades before iterating
MIN_WAIT_SECS    = 300   # Always wait at least 5 min after restart (let bot settle)
MAX_WAIT_SECS    = 3600  # Hard cap: 60 min max wait
EARLY_TRIGGER_N  = 5     # Can fire early if we have this many trades + strong signal
STRONG_SIGNAL_WR = 85    # WR >= this or <= 15% triggers early fire
POLL_INTERVAL    = 30    # Check every 30 seconds
HOT_STREAK_N     = 5     # Wins in a row to trigger hot streak lock
HOT_STREAK_SECS  = 120   # Must all happen within this many seconds

# ── Helpers ────────────────────────────────────────────────────────────────────
def load(path, default):
    try:
        with open(path, encoding="utf-8") as f:
            return json.load(f)
    except:
        return default

def ts():
    return datetime.datetime.now().strftime("%H:%M:%S")

def count_exits():
    analytics = load(ANALYTICS_PATH, [])
    return sum(1 for t in analytics if t.get("event") == "exit")

def recent_wr_from_baseline(baseline_count, n=10):
    """Win rate of recent trades from this experiment only."""
    analytics = load(ANALYTICS_PATH, [])
    exits = [t for t in analytics if t.get("event") == "exit"]
    exp_exits = exits[baseline_count:]
    if not exp_exits:
        return None
    recent = exp_exits[-n:]
    wins = sum(1 for t in recent if t.get("outcome") == "WIN")
    return round(wins / len(recent) * 100, 1)

def get_balance():
    state = load(BOT_STATE_PATH, {})
    return state.get("balance", 0)


def detect_hot_streak(baseline_count, n=HOT_STREAK_N, window=HOT_STREAK_SECS):
    """Return True if last N trades from this experiment were all wins within window seconds."""
    analytics = load(ANALYTICS_PATH, [])
    exits = [t for t in analytics if t.get("event") == "exit"]
    exp_exits = exits[baseline_count:]
    if len(exp_exits) < n:
        return False
    recent = exp_exits[-n:]
    if not all(t.get("outcome") == "WIN" for t in recent):
        return False
    times = [t.get("entry_time", 0) for t in recent]
    if not times[0]:
        return False
    return (times[-1] - times[0]) <= window

# ── Main ───────────────────────────────────────────────────────────────────────
def main():
    # Load experiment state written by iterate.py — gives exact trade baseline
    exp_state = load(EXPERIMENT_STATE_PATH, {})
    baseline  = exp_state.get("start_trade_count", count_exits())
    exp_label = exp_state.get("label", "unknown")
    exp_ts    = exp_state.get("start_ts", "unknown")

    start_time = time.time()
    start_bal  = get_balance()

    print(f"\n[{ts()}] ================================================", flush=True)
    print(f"[{ts()}]  SMART LOOP — Watching for experiment trade data", flush=True)
    print(f"[{ts()}] ================================================", flush=True)
    print(f"[{ts()}]  Experiment : {exp_label}", flush=True)
    print(f"[{ts()}]  Started    : {exp_ts}", flush=True)
    print(f"[{ts()}]  Baseline   : {baseline} total trades | Balance: ${start_bal:.2f}", flush=True)
    print(f"[{ts()}]  Trigger    : {MIN_NEW_TRADES}+ new trades AND {MIN_WAIT_SECS//60}+ min elapsed", flush=True)
    print(f"[{ts()}]  Early fire : {EARLY_TRIGGER_N}+ trades with WR >={STRONG_SIGNAL_WR}% or <={100-STRONG_SIGNAL_WR}%", flush=True)
    print(f"[{ts()}]  Hard cap   : {MAX_WAIT_SECS//60} min max", flush=True)
    print(f"[{ts()}] ================================================\n", flush=True)

    last_print = 0

    while True:
        elapsed    = time.time() - start_time
        current    = count_exits()
        new_trades = current - baseline
        remaining  = MAX_WAIT_SECS - elapsed
        wr         = recent_wr_from_baseline(baseline)
        wr_str     = f"{wr}%" if wr is not None else "n/a"
        bal        = get_balance()

        # TRIGGER 3: Hard cap
        if elapsed >= MAX_WAIT_SECS:
            print(f"\n[{ts()}] HARD CAP reached ({MAX_WAIT_SECS//60} min).", flush=True)
            print(f"[{ts()}]   {new_trades} new trades — forcing iteration (may be dead market).", flush=True)
            break

        # TRIGGER 1: Primary — enough trades + enough time
        if new_trades >= MIN_NEW_TRADES and elapsed >= MIN_WAIT_SECS:
            print(f"\n[{ts()}] PRIMARY TRIGGER fired.", flush=True)
            print(f"[{ts()}]   {new_trades} new trades in {elapsed/60:.1f} min | WR: {wr_str} | Balance: ${bal:.2f}", flush=True)
            break

        # TRIGGER 2: Early — strong unmistakable signal
        if new_trades >= EARLY_TRIGGER_N and elapsed >= MIN_WAIT_SECS and wr is not None:
            if wr >= STRONG_SIGNAL_WR or wr <= (100 - STRONG_SIGNAL_WR):
                direction = "DOMINANT WIN" if wr >= STRONG_SIGNAL_WR else "DOMINANT LOSS"
                print(f"\n[{ts()}] EARLY TRIGGER: {direction} signal!", flush=True)
                print(f"[{ts()}]   {new_trades} trades, WR={wr_str} — iterating early.", flush=True)
                break

        # TRIGGER 4: Hot streak — N wins in quick succession
        if new_trades >= HOT_STREAK_N and detect_hot_streak(baseline):
            pnl_streak = sum(t.get("pnl", 0) for t in load(ANALYTICS_PATH, []) if t.get("event") == "exit")[baseline:baseline+new_trades] if False else ""
            print(f"\n[{ts()}] *** HOT STREAK DETECTED! ***", flush=True)
            print(f"[{ts()}]   {HOT_STREAK_N} consecutive wins in under {HOT_STREAK_SECS}s — locking champion params!", flush=True)
            print(f"[{ts()}]   Flagging for CONFIRM_CHAMPION next iteration.", flush=True)
            exp_upd = load(EXPERIMENT_STATE_PATH, {})
            exp_upd["hot_streak"] = True
            exp_upd["hot_streak_new_trades"] = new_trades
            with open(EXPERIMENT_STATE_PATH, "w", encoding="utf-8") as fh:
                import json as _j; _j.dump(exp_upd, fh, indent=2)
            break

        # Status every 60 seconds
        if elapsed - last_print >= 60:
            mins_e = int(elapsed // 60)
            secs_e = int(elapsed % 60)
            mins_r = int(remaining // 60)
            need   = max(0, MIN_NEW_TRADES - new_trades)
            print(
                f"[{ts()}]  {mins_e}m{secs_e:02d}s elapsed | "
                f"Trades: {new_trades}/{MIN_NEW_TRADES} (need {need} more) | "
                f"WR: {wr_str} | Balance: ${bal:.2f} | Cap in: {mins_r}m",
                flush=True
            )
            last_print = elapsed

        time.sleep(POLL_INTERVAL)

    print(f"[{ts()}]  Handing off to iterate.py.\n", flush=True)

if __name__ == "__main__":
    main()

