"""
fixed_entries.py -- TEST-ONLY entry module (simulator, never live).

Buys exactly the entries listed in a file (sim/entries/*.json): symbol,
time (UTC) and stop -- so different EXIT rules can be compared on the
very same entries. simulate.py --fixed-entries FILE loads it
automatically and points cfg["file"] at FILE.
"""
import json
from datetime import datetime

from rules_api import EntryDecision, MarketView

NAME = "fixed"
_cache = {}
_done = {}   # (date, symbol) -> entries used (module level: the core clears
             # per-symbol state after a fill, which would re-buy the same entry)


def _entries(path):
    if path not in _cache:
        out = {}
        for e in json.load(open(path))["entries"]:
            out.setdefault((e["date"], e["symbol"]), []).append(
                {**e, "_t": datetime.fromisoformat(e["time"])})
        _cache[path] = out
    return _cache[path]


def evaluate(view: MarketView, state: dict) -> EntryDecision:
    key = (view.now.date().isoformat(), view.symbol)
    todo = _entries(view.cfg["file"]).get(key, [])
    done = _done.get(key, 0)
    if done >= len(todo):
        return EntryDecision(state="DONE", reason="no more listed entries")
    e = todo[done]
    if view.now < e["_t"]:
        return EntryDecision(state="WAIT", reason=f"listed entry at {e['time']}")
    _done[key] = done + 1
    if e["stop"] >= view.price:
        return EntryDecision(state="SKIP", reason=f"price {view.price} already at/below listed stop {e['stop']}")
    return EntryDecision(True, stop=e["stop"], state="BUY", reason=f"listed entry {e['time']}",
                         plan={k: v for k, v in e.items() if not k.startswith("_")})
