# src/backtest_context.py

from datetime import datetime
from typing import Optional, Any, Dict, TYPE_CHECKING

# 使用 TYPE_CHECKING 避免循环导入，只在类型检查时导入 BacktestEngine
if TYPE_CHECKING:
    from .backtest_engine import BacktestEngine
    from .execution_simulator import ExecutionSimulator
    from .data_manager import DataManager
    from .core_data import Bar, Order # 确保导入 Order

class BacktestContext:
    """
    回测上下文，用于连接策略与数据管理器、模拟器。
    策略通过此上下文与回测引擎进行交互。
    """
    def __init__(self, data_manager: 'DataManager', simulator: 'ExecutionSimulator'):
        """
        初始化回测上下文。

        Args:
            data_manager (DataManager): 数据管理器实例。
            simulator (ExecutionSimulator): 交易模拟器实例。
        """
        self._data_manager = data_manager
        self._simulator = simulator
        self._current_bar: Optional['Bar'] = None
        self._engine: Optional['BacktestEngine'] = None # 添加对引擎的引用

    def set_current_bar(self, bar: 'Bar'):
        """
        设置当前正在处理的 K 线数据。
        由 BacktestEngine 调用。
        """
        self._current_bar = bar

    def get_current_bar(self) -> Optional['Bar']:
        """
        获取当前正在处理的 K 线数据。
        策略可以通过此方法获取最新 K 线。
        """
        return self._current_bar

    def get_current_time(self) -> datetime:
        """
        获取当前模拟时间。
        """
        return self._simulator.get_current_time()

    def get_current_positions(self) -> Dict[str, int]:
        """
        获取当前所有持仓。
        """
        return self._simulator.get_current_positions()

    def get_pending_orders(self) -> Dict[str, 'Order']:
        """
        获取当前所有待处理（未成交）订单。
        """
        return self._simulator.get_pending_orders()

    def get_account_cash(self) -> float:
        """
        获取当前可用现金。
        """
        return self._simulator.cash

    def get_average_position_price(self, symbol: str) -> Optional[float]:
        """
        获取指定合约的平均持仓成本。
        """
        return self._simulator.get_average_position_price(symbol)

    def send_order(self, order: 'Order') -> Optional['Order']:
        """
        策略通过此方法发送订单到模拟器。
        """
        return self._simulator.send_order_to_pending(order)

    def cancel_order(self, order_id: str) -> bool:
        """
        策略通过此方法取消指定ID的订单。
        """
        return self._simulator.cancel_order(order_id)

    def set_engine(self, engine: 'BacktestEngine'):
        """
        设置对 BacktestEngine 实例的引用。
        由 BacktestEngine 在初始化时调用，用于允许 Context 访问 Engine 的状态。
        """
        self._engine = engine

    def get_bar_history(self):
        return self._engine.get_bar_history()

    @property
    def is_rollover_bar(self) -> bool:
        """
        属性：判断当前 K 线是否为换月 K 线（即新合约的第一根 K 线）。
        用于在换月时禁止策略开仓。
        """
        if self._engine:
            return self._engine.is_rollover_bar
        # 如果没有设置引擎引用，默认不认为是换月 K 线
        # 这通常发生在测试 Context 本身时，或 Engine 初始化不完整的情况。
        return False
