"""Unit tests for live ORB opening-burst entry parity."""
from __future__ import annotations

import datetime as dt
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
from zoneinfo import ZoneInfo

from apps.orb_trader.engine import ORBTradingEngine

_DATE = "2026-01-05"
_ET = ZoneInfo("America/New_York")


def _make_engine() -> ORBTradingEngine:
    params = SimpleNamespace(
        sim_bar_minutes=5,
        orb_minutes=5,
        order_timeout_minutes=25,
        live_breakout_use_bar_high=False,
        market_thrust_liquid_continuation_entry_mode="opening_burst",
        opening_burst_liquid_max_entry_minutes_after_open=15,
        daily_budget_reset=True,
        drawdown_governor_threshold=None,
        drawdown_governor_min_scale=0.30,
        streak_sizing_win_bonus=None,
        streak_sizing_loss_penalty=None,
        streak_sizing_max=2.5,
        streak_sizing_min=0.5,
        max_simultaneous_entries=3,
        atr_stop_multiplier=0.75,
        risk_per_trade_pct=0.05,
        max_position_pct=0.70,
    )
    session = SimpleNamespace(
        session_id="test-session",
        session_name="test",
        initial_equity=10_000.0,
    )
    state = MagicMock()
    state.get_open_positions.return_value = []
    state.get_equity.return_value = 10_000.0
    state.get_peak_equity.return_value = 10_000.0
    state.get_daily_state.return_value = SimpleNamespace(kill_switch=False)

    broker = MagicMock()
    broker.get_account.return_value = SimpleNamespace(buying_power=100_000.0)
    broker.submit_market_buy.return_value = SimpleNamespace(id="buy-1")
    broker.get_order.return_value = SimpleNamespace(
        status="filled",
        filled_avg_price=100.50,
    )

    eng = object.__new__(ORBTradingEngine)
    eng._session = session
    eng._params = params
    eng._state = state
    eng._broker = broker
    eng._log_callback = None
    eng._date_str = _DATE
    eng._day_size_scale = 1.0
    eng._market_orb_quality_max_trades = None
    eng._market_orb_quality_reason = None
    eng._pending_cands = [
        {
            "ticker": "BURST",
            "direction": "bullish",
            "orb_bar": {
                "timestamp": f"{_DATE}T09:30:00-05:00",
                "open": 100.0,
                "high": 105.0,
                "low": 99.0,
                "close": 104.0,
                "volume": 1_000,
            },
            "atr": 2.0,
            "rvol": 6.0,
            "gap_pct": 0.08,
            "score": 0.95,
            "market_thrust_liquid_continuation": True,
        }
    ]
    eng._candidates = list(eng._pending_cands)
    eng._now_et = lambda: dt.datetime(2026, 1, 5, 9, 40, tzinfo=_ET)  # type: ignore[method-assign]
    return eng


@patch("apps.orb_trader.engine.time")
@patch("apps.orb_trader.engine.get_snapshots")
def test_market_thrust_opening_burst_enters_without_snapshot_breakout(
    mock_snapshots,
    mock_time,
):
    mock_snapshots.return_value = {"BURST": SimpleNamespace(price=100.0)}
    eng = _make_engine()

    result = eng.run_breakout_check(_DATE)

    assert result["filled"] == 1
    eng._broker.submit_market_buy.assert_called_once()
    pos = eng._state.save_position.call_args.args[0]
    assert pos.ticker == "BURST"
    assert pos.trigger_type == "market_thrust_opening_burst"
    assert pos.entry_price == 100.50
