#!/usr/bin/env python3
"""
strategy_adapters.py — 将现有 signal_generators 适配为 SignalStrategy 接口。
零侵入：不修改任何现有代码，仅做薄包装。
"""
import sys
from pathlib import Path

ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(ROOT))

from contracts.strategy_interface import SignalStrategy


class EmaRsiBbAdapter(SignalStrategy):
    """
    EMA + RSI + BB 策略适配器。
    包装 signal_generators.ema_macd_signal.EMAMacdSignalGenerator。
    """

    def __init__(self, params: dict = None):
        from signal_generators.ema_macd_signal import EMAMacdSignalGenerator
        self._gen = EMAMacdSignalGenerator(params)

    @property
    def name(self) -> str:
        return "ema_rsi_bb"

    def analyze(self, bars: list[dict], params: dict) -> dict:
        # 参数名映射: grid search 简写 → signal generator 全名
        mapped = dict(params)
        if "sl_atr" in mapped:
            mapped.setdefault("sl_atr_mult_trend", float(mapped.pop("sl_atr")))
            mapped.setdefault("sl_atr_mult_range", mapped["sl_atr_mult_trend"])
        if "tp_atr" in mapped:
            mapped.setdefault("tp_atr_mult_trend", float(mapped.pop("tp_atr")))
            mapped.setdefault("tp_atr_mult_range", mapped["tp_atr_mult_trend"])
        return self._gen.analyze(bars, mapped)

    def param_grid(self) -> dict[str, list]:
        return {
            "ema_short": [7, 9, 12],
            "ema_long": [21, 26, 50],
            "sl_atr": [1.0, 1.5, 2.0],
            "tp_atr": [1.5, 2.0, 3.0],
        }

    def default_params(self) -> dict:
        return {
            "ema_short": 9,
            "ema_long": 21,
            "sl_atr": 1.0,
            "tp_atr": 3.0,
        }


class GridStrategyAdapter(SignalStrategy):
    """
    网格策略适配器。
    基于 bridge/grid_strategy.py 的逻辑（区间高抛低吸）。
    注意：网格策略的信号生成逻辑较简单，回测时需特殊处理持仓管理。
    """

    def __init__(self, params: dict = None):
        self._params = params or {}

    @property
    def name(self) -> str:
        return "grid"

    def analyze(self, bars: list[dict], params: dict) -> dict:
        """简化的网格信号：基于价格在区间内的位置生成 BUY/SELL"""
        if len(bars) < 2:
            return {"action": "HOLD"}

        current = bars[-1]
        close = float(current.get("close", 0))
        high = float(current.get("high", close))
        low = float(current.get("low", close))

        zone_width = float(params.get("zone_width", 80))
        sl_distance = float(params.get("sl_distance", 30))
        tp1_mult = float(params.get("tp1_atr_mult", 0.8))
        atr = float(params.get("atr", 3.0))

        # 用最近 20 根K线高低点确定区间
        recent_high = max(float(b.get("high", 0)) for b in bars[-20:])
        recent_low = min(float(b.get("low", float("inf"))) for b in bars[-20:])

        if recent_high <= recent_low:
            return {"action": "HOLD"}

        # 在区间下沿附近 → BUY
        if low <= recent_low + zone_width * 0.3:
            entry = round(low, 3)
            return {
                "action": "OPEN", "side": "BUY", "regime": "RANGING",
                "entry": entry,
                "sl": round(entry - sl_distance, 3),
                "tp": round(entry + tp1_mult * atr, 3),
                "confidence": 0.65,
            }
        # 在区间上沿附近 → SELL
        if high >= recent_high - zone_width * 0.3:
            entry = round(high, 3)
            return {
                "action": "OPEN", "side": "SELL", "regime": "RANGING",
                "entry": entry,
                "sl": round(entry + sl_distance, 3),
                "tp": round(entry - tp1_mult * atr, 3),
                "confidence": 0.65,
            }

        return {"action": "HOLD"}

    def param_grid(self) -> dict[str, list]:
        return {
            "zone_width": [60, 80, 100, 120],
            "sl_distance": [20, 30, 40, 50],
            "tp1_atr_mult": [0.5, 0.8, 1.0, 1.5],
            "cooldown_bars": [3, 5, 8],
        }

    def default_params(self) -> dict:
        return {
            "zone_width": 80,
            "sl_distance": 30,
            "tp1_atr_mult": 0.8,
            "cooldown_bars": 5,
            "atr": 3.0,
        }


class CompositeStrategyAdapter(SignalStrategy):
    """
    多策略聚合适配器。
    包装 signal_generators.composite_signal.CompositeSignalGenerator。
    """

    def __init__(self, params: dict = None):
        from signal_generators.composite_signal import CompositeSignalGenerator
        self._gen = CompositeSignalGenerator(params)

    @property
    def name(self) -> str:
        return "composite"

    def analyze(self, bars: list[dict], params: dict) -> dict:
        return self._gen.analyze(bars, params)

    def param_grid(self) -> dict[str, list]:
        return {
            "composite_hold_threshold": [0.30, 0.40, 0.55],
            "composite_alignment_bonus": [0.05, 0.10, 0.15],
            "composite_conflict_penalty": [0.20, 0.30, 0.45],
        }

    def default_params(self) -> dict:
        return {
            "composite_hold_threshold": 0.40,
            "composite_alignment_bonus": 0.10,
            "composite_conflict_penalty": 0.30,
        }
