"""
sf_watchlist_day.py -- [2026-10-02] Every stock the trade bot watched on a day, on both Star
Follow versions; buys only while the bot was watching that stock (its scan windows), exits any
time until 15:55. Compares with the bot's real trades.
  ORIGINAL  star_follow.py: all playbook days, old marks, trigger 10 in 5 min, no stop
  LATEST    sf3: winners-only, confirmed marks, market+gap (lib_v2), still-matching exit (80)
    python3 sf_watchlist_day.py 2026-10-02
"""
import json
import sys
from datetime import datetime
from pathlib import Path
from zoneinfo import ZoneInfo

import numpy as np

HERE = Path(__file__).resolve().parent
TRADE = Path("/var/www/screener/trade")
sys.path.insert(0, str(HERE)); sys.path.insert(0, str(TRADE))
import reference_trader as RT
import star_follow as SF
import sf3_batch as S3
import lib_v2 as L2
import reference as REF
from alpaca_client import get_client

ET = ZoneInfo("America/New_York")
hm = lambda m: f"{9 + (30 + m) // 60}:{(30 + m) % 60:02d}"


def windows(day):
    import ast
    scans = []
    for line in open(TRADE / "logs" / f"trade_bot_{day}.log"):
        if "[SCAN]" in line and "candidates selected" in line:
            t = line[11:16]
            scans.append(((int(t[:2]) - 9) * 60 + int(t[3:]) - 30, ast.literal_eval(line[line.rindex(": [") + 2:].strip())))
    win = {}
    for i, (m, syms) in enumerate(scans):
        end = scans[i + 1][0] if i + 1 < len(scans) else 345
        for s in syms:
            win.setdefault(s, []).append((m, end))
    return win


def main(day):
    win = windows(day)
    syms = list(win)
    c = get_client()
    d0 = datetime.fromisoformat(day).replace(tzinfo=ET)
    rows = {}
    for s in syms + ["SPY", "IWM"]:
        rows[s] = [[b.timestamp, float(b.open), float(b.high), float(b.low), float(b.close), float(b.volume)]
                   for b in c.get_minute_bars(s, start=d0.replace(hour=9, minute=30), end=d0.replace(hour=16), limit=1000)]
    bench = []
    for b in ("SPY", "IWM"):
        by = L2._minutes(rows[b]); arr = np.zeros(390, np.float32)
        if by:
            o = by[min(by)][1]; last = o
            for m in range(390):
                last = by[m][4] if m in by else last
                arr[m] = (last / o - 1) * 100
        bench.append(arr)
    bot = {}
    for l in open(TRADE / "data" / "trades" / f"{day}_trades.jsonl"):
        t = json.loads(l); bot.setdefault(t["symbol"], []).append(t.get("pl_pct") or 0)
    res = {"original": [], "latest": []}
    # ORIGINAL
    lib = RT.Lib(); marks = SF.load_marks()
    for s in syms:
        ref = REF.load(day, s)
        a = RT.day_arrays(rows[s], ref) if ref else None
        if a is None:
            continue
        ok = lambda m, w=win[s]: any(x <= m < y for x, y in w)
        tr, _ = SF.star_follow(lib, marks, day, a, stop_pct=100.0, can_buy=ok)
        res["original"] += [{"sym": s, **t} for t in tr]
    del lib
    # LATEST
    lib = L2.Lib(); m3 = S3.load(); wmask = np.array([k in m3 for k in lib.keys]); nb, ns = S3.normal_rates(m3)
    S3.MIN_MATCH = 80
    if "--band" in sys.argv:
        S3.MODE = "band"
    if "--since" in sys.argv:
        S3.MODE = "since"
    for s in syms:
        ref = REF.load(day, s)
        a = L2.day_arrays(rows[s], ref, day, tuple(bench)) if ref else None
        if a is None:
            continue
        ok = lambda m, w=win[s]: any(x <= m < y for x, y in w)
        res["latest"] += [{"sym": s, **t} for t in S3.run_day(lib, wmask, m3, nb, ns, day, a, can_buy=ok)]
    json.dump(res, open(HERE / f"sf_watchlist_{day}{'_' + S3.MODE if S3.MODE != 'count' else ''}.json", "w"), default=float)
    print(f"{len(syms)} watched stocks on {day}")
    for v, T in res.items():
        key = "pl_pct" if v == "original" else "pl"
        p = np.array([t[key] for t in T]) if T else np.array([0.0])
        traded = sorted({t["sym"] for t in T})
        print(f"\n== {v.upper()}: {len(T)} trades on {len(traded)} stocks, win {(p > 0).mean():.0%}, avg {p.mean():+.2f}%, "
              f"sum {p.sum():+.1f}% (0.1% cost per trade) | best {p.max():+.1f}%, worst {p.min():+.1f}%")
        for t in sorted(T, key=lambda t: -t[key])[:5]:
            print(f"   best: {t['sym']:5} {hm(t['buy_m'])} {t['buy']:.2f} -> {hm(t['sell_m'])} {t['sell']:.2f} {t[key]:+.2f}% [{t['why']}]")
        for t in sorted(T, key=lambda t: t[key])[:5]:
            print(f"   worst: {t['sym']:5} {hm(t['buy_m'])} {t['buy']:.2f} -> {hm(t['sell_m'])} {t['sell']:.2f} {t[key]:+.2f}% [{t['why']}]")
    bp = [x for v in bot.values() for x in v]
    print(f"\n== BOT (real): {len(bp)} trades, sum {sum(bp):+.2f}% (before the 0.1% cost), stocks {sorted(bot)}")


if __name__ == "__main__":
    main(sys.argv[1])
