"""Replays history bar by bar through the SAME Engine used live, with fees and slippage."""
from .broker import SimBroker
from .engine import Engine
from .journal import Journal
from .metrics import summarize
from .risk import Risk


def run_backtest(df, params, cfg, warmup=150, window=300):
    j = Journal(":memory:")
    start = cfg["sim_start_balance"]
    v = j.new_version(params, start)
    broker = SimBroker(start, cfg["fee_rate"], cfg["slippage_bps"])
    broker.set_price(float(df.close.iloc[0]))
    eng = Engine(cfg, broker, j, Risk(cfg), v, params)
    for i in range(warmup, len(df)):
        win = df.iloc[max(0, i - window + 1): i + 1]
        bar = df.iloc[i]
        eng.step(win, win.index[-1], bar_high=bar.high, bar_low=bar.low, price=bar.close)
        j.log_equity(v, broker.equity(), win.index[-1])
    last = df.iloc[-1]
    broker.set_price(float(last.close))
    eng.close_all("END", df.index[-1])
    trades = j.trades(v)
    out = summarize(trades, start, j.equity_series(v))
    out["final_equity"] = round(broker.equity(), 2)
    return out, trades


def split_backtest(df, params, cfg, train_frac=0.7):
    """Tune on the first part, judge on the part the strategy has never seen."""
    cut = int(len(df) * train_frac)
    train, _ = run_backtest(df.iloc[:cut], params, cfg)
    test, trades = run_backtest(df.iloc[cut - 300:], params, cfg)
    return {"train": train, "unseen_test": test}, trades
