"""
Trading Context 固定欄位存取器

基於 schema.py 中定義的 struct 欄位，提供簡潔的屬性存取方式，
避免繁瑣的 `.struct.field()` 呼叫。

Usage:
    from tradepose_client.builder import TradingContext
    import polars as pl

    # 簡潔存取（返回 pl.Expr）
    entry_price = TradingContext.base.entry_price
    highest = TradingContext.advanced_entry.highest_since_entry
    bars = TradingContext.advanced_exit.bars_since_entry

    # 用於策略條件表達式
    condition = TradingContext.base.bars_in_position > 50
    stop_loss_price = TradingContext.advanced_entry.entry_price - pl.col("atr") * 2
"""

import polars as pl


class TradingContextProxy:
    """
    Trading Context 欄位存取代理

    為 base_trading_context, advanced_entry_trading_context,
    advanced_exit_trading_context 提供統一的屬性存取介面。

    Args:
        context_name: 上下文欄位名稱（如 "base_trading_context"）
    """

    def __init__(
        self,
        context_name: str,
    ):
        self._context_name = context_name

    @property
    def entry_price(self) -> pl.Expr:
        """
        進場價格

        Returns:
            pl.Expr: Polars 表達式，可直接用於條件或價格計算
        """
        return pl.col(self._context_name).struct.field("position_entry_price")

    @property
    def bars_in_position(self) -> pl.Expr:
        """
        持倉 K 線數

        Returns:
            pl.Expr: Polars 表達式

        Note:
            Rust worker 統一使用 "bars_since_entry" 欄位名稱
        """
        return pl.col(self._context_name).struct.field("bars_since_entry")

    @property
    def bars_since_entry(self) -> pl.Expr:
        """
        進場以來 K 線數（bars_in_position 的別名）

        Returns:
            pl.Expr: Polars 表達式
        """
        return self.bars_in_position

    @property
    def highest_since_entry(self) -> pl.Expr:
        """
        進場以來最高價（即時版本，包含當前 bar）

        Returns:
            pl.Expr: Polars 表達式

        Warning:
            此欄位包含當前 bar 的 high，在 bar open 時刻該值尚未發生。
            用於條件判斷時，請使用 `prev_highest_since_entry`。
        """
        return pl.col(self._context_name).struct.field("highest_since_entry")

    @property
    def lowest_since_entry(self) -> pl.Expr:
        """
        進場以來最低價（即時版本，包含當前 bar）

        Returns:
            pl.Expr: Polars 表達式

        Warning:
            此欄位包含當前 bar 的 low，在 bar open 時刻該值尚未發生。
            用於條件判斷時，請使用 `prev_lowest_since_entry`。
        """
        return pl.col(self._context_name).struct.field("lowest_since_entry")

    @property
    def base_position_id(self) -> pl.Expr:
        """
        Base Position ID（用於 shift().over() 確保不跨越 position 邊界）

        Returns:
            pl.Expr: Polars 表達式
        """
        return pl.col("base_position_id")

    @property
    def prev_highest_since_entry(self) -> pl.Expr:
        """
        進場以來最高價（安全版本，到前一根 bar 為止）

        此欄位使用 `shift().over([base_position_id])` 確保：
        1. 取得「到前一根 bar 為止」的最高點，符合 Open-Driven Design
        2. shift 只在同一個 position 內進行，不會跨越 position 邊界

        Returns:
            pl.Expr: Polars 表達式，適用於條件判斷和 price_expr

        Examples:
            >>> # 用於 Breakeven 條件
            >>> TradingContext.advanced_entry.prev_highest_since_entry > threshold
            >>>
            >>> # 用於 Trailing Stop price
            >>> TradingContext.advanced_entry.prev_highest_since_entry - atr.col()
        """
        return self.highest_since_entry.shift().over([self.base_position_id])

    @property
    def prev_lowest_since_entry(self) -> pl.Expr:
        """
        進場以來最低價（安全版本，到前一根 bar 為止）

        此欄位使用 `shift().over([base_position_id])` 確保：
        1. 取得「到前一根 bar 為止」的最低點，符合 Open-Driven Design
        2. shift 只在同一個 position 內進行，不會跨越 position 邊界

        Returns:
            pl.Expr: Polars 表達式，適用於條件判斷和 price_expr

        Examples:
            >>> # 用於 SHORT 的 Breakeven 條件
            >>> TradingContext.advanced_entry.prev_lowest_since_entry < threshold
            >>>
            >>> # 用於 SHORT 的 Trailing Stop price
            >>> TradingContext.advanced_entry.prev_lowest_since_entry + atr.col()
        """
        return self.lowest_since_entry.shift().over([self.base_position_id])


class TradingContext:
    """
    Trading Context 統一存取器

    提供三種 trading context 的屬性存取：
    - base: base_trading_context
    - advanced_entry: advanced_entry_trading_context
    - advanced_exit: advanced_exit_trading_context

    Usage:
        # Base context（Base Blueprint 生成）
        TradingContext.base.entry_price
        TradingContext.base.bars_in_position
        TradingContext.base.highest_since_entry
        TradingContext.base.lowest_since_entry

        # Advanced Entry context（Advanced Entry Triggers 使用）
        TradingContext.advanced_entry.entry_price
        TradingContext.advanced_entry.bars_since_entry
        TradingContext.advanced_entry.highest_since_entry
        TradingContext.advanced_entry.lowest_since_entry

        # Advanced Exit context（Advanced Exit Triggers 使用）
        TradingContext.advanced_exit.entry_price
        TradingContext.advanced_exit.bars_since_entry
        TradingContext.advanced_exit.highest_since_entry
        TradingContext.advanced_exit.lowest_since_entry

    Examples:
        # Stop Loss（Long）
        stop_loss_price = (
            TradingContext.advanced_entry.entry_price -
            pl.col("atr") * 2
        )

        # Trailing Stop（Long）
        trailing_stop_price = (
            TradingContext.advanced_entry.highest_since_entry -
            pl.col("atr") * 2
        )

        # 持倉時間過濾
        timeout_condition = TradingContext.advanced_entry.bars_since_entry > 100
    """

    base = TradingContextProxy("base_trading_context")
    advanced_entry = TradingContextProxy("advanced_entry_trading_context")
    advanced_exit = TradingContextProxy("advanced_exit_trading_context")


# 向後相容的別名
BaseContext = TradingContext.base
AdvancedEntryContext = TradingContext.advanced_entry
AdvancedExitContext = TradingContext.advanced_exit
