"""
Helper Functions for Strategy Configuration

Provides convenient factory functions for creating IndicatorSpec, Trigger, and Blueprint instances.
"""

from typing import Any, Dict, List, Optional, Union

import polars as pl
from tradepose_models.enums import Freq, OrderStrategy, TradeDirection, TrendType
from tradepose_models.strategy import Blueprint, IndicatorSpec, Trigger


def create_indicator_spec(
    freq: Union[Freq, str],
    indicator: Dict[str, Any],
    instrument: Optional[str] = None,
    shift: int = 1,
) -> IndicatorSpec:
    """創建指標規範（簡化版工廠函數）

    使用 Indicator 靜態類創建 indicator dict，然後傳入此函數

    Args:
        freq: 頻率（使用 Freq enum 或字串）
        indicator: 指標配置（使用 Indicator 靜態類創建）
        instrument: 交易標的（顯示名稱，可選）
        shift: 位移（預設 1）

    Returns:
        IndicatorSpec 實例，可直接調用 .col() 獲取 Polars 表達式

    Examples:
        >>> from tradepose_models import Freq, Indicator, create_indicator_spec
        >>>
        >>> # 方式 1: 使用 Freq enum + Indicator 靜態類
        >>> sma_20 = create_indicator_spec(
        ...     freq=Freq.MIN_1,
        ...     indicator=Indicator.sma(period=20),
        ...     instrument="ES"
        ... )
        >>> print(sma_20.display_name())  # "ES_1min_SMA|20.close"
        >>>
        >>> # 方式 2: 使用字串（向後兼容）
        >>> atr_14 = create_indicator_spec(
        ...     freq="1D",
        ...     indicator=Indicator.atr(period=14),
        ...     shift=2
        ... )
        >>> print(atr_14.display_name())  # "1D_ATR|14_s2"
        >>>
        >>> # 方式 3: SuperTrend
        >>> st = create_indicator_spec(
        ...     freq=Freq.MIN_5,
        ...     indicator=Indicator.supertrend(multiplier=3.0, volatility_column="atr"),
        ...     instrument="BTC"
        ... )
        >>> print(st.display_name())  # "BTC_5min_ST|3.0x_atr"
        >>>
        >>> # 在策略中使用（最簡潔的寫法）
        >>> sma_50 = create_indicator_spec(Freq.MIN_1, Indicator.sma(50), "ES")
        >>> conditions = [
        ...     sma_20.col() > sma_50.col(),
        ...     pl.col("volume") > 1000
        ... ]
    """
    return IndicatorSpec(
        instrument=instrument,
        instrument_id=None,  # Will be populated by Gateway
        freq=freq,
        shift=shift,
        indicator=indicator,
    )


def create_trigger(
    name: str,
    conditions: List[pl.Expr],
    offset_expr: pl.Expr,
    order_strategy: OrderStrategy = OrderStrategy.IMMEDIATE_ENTRY,
    priority: int = 1,
    note: str = "",
) -> Trigger:
    """創建觸發器

    Args:
        name: 觸發器名稱
        conditions: 條件列表，可直接使用 pl.col() 等
        offset_expr: 偏移量表達式（距離）。Rust 端會根據 order_strategy 和 direction 自動計算實際價格。
        order_strategy: 訂單策略（可使用 OrderStrategy enum 或字串，預設 OrderStrategy.IMMEDIATE_ENTRY）
        priority: 優先級
        note: 備註說明

    Returns:
        Trigger 實例

    Example:
        >>> # StopLoss: Rust 會計算 entry_price - offset (Long) 或 entry_price + offset (Short)
        >>> sl = create_trigger(
        ...     name="sl",
        ...     conditions=[],
        ...     offset_expr=pl.col("atr") * 2.0,
        ...     order_strategy=OrderStrategy.STOP_LOSS
        ... )
        >>>
        >>> # ImmediateEntry: offset_expr 會被忽略，使用 open
        >>> entry = create_trigger(
        ...     name="entry",
        ...     conditions=[pl.col("sma_30") > pl.col("sma_50")],
        ...     offset_expr=pl.lit(0.0),  # Neutral 策略忽略 offset
        ...     order_strategy=OrderStrategy.IMMEDIATE_ENTRY
        ... )
    """
    return Trigger(
        name=name,
        conditions=conditions,
        offset_expr=offset_expr,
        order_strategy=order_strategy,
        priority=priority,
        note=note,
    )


def create_blueprint(
    name: str,
    direction: TradeDirection,
    entry_triggers: List[Trigger],
    exit_triggers: List[Trigger],
    trend_type: TrendType = TrendType.TREND,
    entry_first: bool = True,
    note: str = "",
) -> Blueprint:
    """創建藍圖

    Example:
        >>> entry_trigger = create_trigger(
        ...     name="entry",
        ...     conditions=[pl.col("sma_30") > pl.col("sma_50")],
        ...     offset_expr=pl.lit(0.0),  # ImmediateEntry 忽略 offset
        ...     order_strategy=OrderStrategy.IMMEDIATE_ENTRY
        ... )
        >>>
        >>> exit_trigger = create_trigger(
        ...     name="exit",
        ...     conditions=[pl.col("sma_30") < pl.col("sma_50")],
        ...     offset_expr=pl.lit(0.0),  # ImmediateExit 忽略 offset
        ...     order_strategy=OrderStrategy.IMMEDIATE_EXIT
        ... )
        >>>
        >>> blueprint = create_blueprint(
        ...     name="my_strategy",
        ...     direction=TradeDirection.LONG,
        ...     entry_triggers=[entry_trigger],
        ...     exit_triggers=[exit_trigger]
        ... )
    """
    return Blueprint(
        name=name,
        direction=direction,
        trend_type=trend_type,
        entry_first=entry_first,
        note=note,
        entry_triggers=entry_triggers,
        exit_triggers=exit_triggers,
    )
