"""
Trend strategy
Auto-generated by StrategyCodeGenerator.
Strategy ID: trend_strategy
"""
from strategy_sdk.interfaces import StrategyPlugin
from strategy_sdk.types import (
    MarketSnapshot,
    PortfolioStateView,
    StrategyInitContext,
    StrategyIntent,
    StrategyManifest,
    StrategyRiskOpinion,
)


class TrendStrategy(StrategyPlugin):
    """Trend strategy"""

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

    def manifest(self):
        return StrategyManifest(
            strategy_id="trend_strategy",
            name="My Trend V1",
            version="1.0.0",
            kind="signal",
            entrypoint="strategies.trend_strategy",
            description="Trend strategy",
            author="AI",
            tags=[["ai-generated"]],
            capabilities=[["intraday"]],
            supported_symbols=["XAUUSD"],
            supported_timeframes=["M5", "M15", "H1"],
            params_schema={"ema_short": {"type": "int", "default": 9, "range": [5, 20]}, "ema_long": {"type": "int", "default": 21, "range": [15, 50]}, "atr_period": {"type": "int", "default": 14, "range": [7, 21]}},
            default_mode="plugin",
            trust_level="sandbox",
        )

    def initialize(self, ctx: StrategyInitContext) -> None:
        self._ctx = ctx
        self._params.update(ctx.config)

    def _calc_ema(self, values, period):
        if not values or period < 1:
            return 0.0
        k = 2.0 / (period + 1.0)
        if len(values) < period:
            return sum(values) / len(values)
        ema = sum(values[:period]) / period
        for v in values[period:]:
            ema = v * k + ema * (1.0 - k)
        return ema

    def on_market_snapshot(self, snapshot: MarketSnapshot) -> StrategyIntent:
        bars = snapshot.bars
        ema_short_period = int(self._params.get("ema_short", 9))
        ema_long_period = int(self._params.get("ema_long", 21))
        atr_period = int(self._params.get("atr_period", 14))
        min_bars = max(ema_long_period + 5, 20)
        if not bars or len(bars) < min_bars:
            return StrategyIntent(
                strategy_id=self.manifest().strategy_id,
                strategy_version="1.0.0",
                config_revision="sandbox",
                instance_id="default",
                action="HOLD",
                side="BUY",
                confidence=0.0,
                reason="insufficient bars",
            )

        close = [float(b.get("close", 0)) for b in bars]
        highs = [float(b.get("high", 0)) for b in bars]
        lows = [float(b.get("low", 0)) for b in bars]
        ema_short = self._calc_ema(close, ema_short_period)
        ema_long = self._calc_ema(close, ema_long_period)

        # ATR calculation
        trs = [
            max(highs[i] - lows[i],
                abs(highs[i] - close[i-1]),
                abs(lows[i] - close[i-1]))
            for i in range(1, len(highs))
        ]
        atr = sum(trs[-atr_period:]) / min(atr_period, len(trs)) if trs else 5.0

        if ema_short > ema_long:
            return StrategyIntent(
                strategy_id=self.manifest().strategy_id,
                strategy_version="1.0.0",
                config_revision="sandbox",
                instance_id="default",
                action="BUY",
                side="BUY",
                confidence=0.65,
                reason="EMA crossover bullish",
                entry_plan={"entry": close[-1]},
                exit_plan={"sl": round(close[-1] - atr * 1.5, 2),
                           "tp": round(close[-1] + atr * 2.5, 2)},
            )
        elif ema_short < ema_long:
            return StrategyIntent(
                strategy_id=self.manifest().strategy_id,
                strategy_version="1.0.0",
                config_revision="sandbox",
                instance_id="default",
                action="SELL",
                side="SELL",
                confidence=0.65,
                reason="EMA crossover bearish",
                entry_plan={"entry": close[-1]},
                exit_plan={"sl": round(close[-1] + atr * 1.5, 2),
                           "tp": round(close[-1] - atr * 2.5, 2)},
            )
        return StrategyIntent(
            strategy_id=self.manifest().strategy_id,
            strategy_version="1.0.0",
            config_revision="sandbox",
            instance_id="default",
            action="HOLD",
            side="BUY",
            confidence=0.0,
            reason="no setup",
        )

    def on_risk_check(
        self,
        intent: StrategyIntent,
        portfolio: PortfolioStateView,
    ) -> StrategyRiskOpinion:
        # NOTE: allow=True by design. Per-strategy risk opinions are advisory only.
        # Hard blocking (circuit breaker, daily loss, session filter, spread, position
        # limits) is enforced centrally by bridge/risk_manager.py.
        reasons = []
        if intent.action == "HOLD":
            return StrategyRiskOpinion(allow=True, reasons=["no action"])
        if intent.confidence < 0.5:
            reasons.append("low confidence")
        if portfolio.position_side != "FLAT" and portfolio.position_side == intent.side:
            reasons.append("already positioned")
        if not reasons:
            reasons.append("signal OK")
        return StrategyRiskOpinion(
            allow=True,
            severity="WARN" if reasons else "INFO",
            score=intent.confidence,
            reasons=reasons,
        )

    def shutdown(self) -> None:
        pass
