"""
Volume spike detection with Wyckoff logic
Auto-generated by StrategyCodeGenerator.
Strategy ID: volume_spike_detection_with_wyckoff_logi
"""
from strategy_sdk.interfaces import StrategyPlugin
from strategy_sdk.types import (
    MarketSnapshot,
    PortfolioStateView,
    StrategyInitContext,
    StrategyIntent,
    StrategyManifest,
    StrategyRiskOpinion,
)


class VolumeSpikeDetectionWithWyckoffLogi(StrategyPlugin):
    """Volume spike detection with Wyckoff logic"""

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

    def manifest(self):
        return StrategyManifest(
            strategy_id="volume_spike_detection_with_wyckoff_logi",
            name="Volume spike detection with Wyckoff logic",
            version="1.0.0",
            kind="signal",
            entrypoint="strategies.volume_spike_detection_with_wyckoff_logi",
            description="Volume spike detection with Wyckoff logic",
            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 on_market_snapshot(self, snapshot: MarketSnapshot) -> StrategyIntent:
        bars = snapshot.bars
        if not bars or len(bars) < 20:
            return StrategyIntent(
                strategy_id=self.manifest().strategy_id,
                strategy_version="1.0.0",
                config_revision="sandbox",
                instance_id="vol",
                action="HOLD",
                side="BUY",
                confidence=0.0,
                reason="insufficient bars",
            )

        closes = [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]
        n = len(closes)
        atr_period = int(self._params.get("atr_period", 14))
        lookback = int(self._params.get("ema_long", 20))
        spike_threshold = float(self._params.get("spike_threshold", 1.5))

        # Range spike detection (price range proxy for volume)
        ranges = [highs[i] - lows[i] for i in range(n)]
        avg_range = sum(ranges[-lookback:]) / lookback
        current_range = ranges[-1]
        range_ratio = current_range / avg_range if avg_range > 0 else 1.0

        entry = closes[-1]
        atr = sum(h - l for h, l in zip(highs[-atr_period:], lows[-atr_period:])) / atr_period

        if range_ratio > spike_threshold and closes[-1] > closes[-2]:
            return StrategyIntent(
                strategy_id=self.manifest().strategy_id,
                strategy_version="1.0.0",
                config_revision="sandbox",
                instance_id="vol",
                action="BUY",
                side="BUY",
                confidence=min(0.75, range_ratio * 0.4),
                reason=f"volume spike bullish (ratio={range_ratio:.1f})",
                entry_plan={"entry": entry},
                exit_plan={"sl": entry - 1.5 * atr, "tp": entry + 3.0 * atr},
            )
        if range_ratio > spike_threshold and closes[-1] < closes[-2]:
            return StrategyIntent(
                strategy_id=self.manifest().strategy_id,
                strategy_version="1.0.0",
                config_revision="sandbox",
                instance_id="vol",
                action="SELL",
                side="SELL",
                confidence=min(0.75, range_ratio * 0.4),
                reason=f"range spike bearish (ratio={range_ratio:.1f})",
                entry_plan={"entry": entry},
                exit_plan={"sl": entry + 1.5 * atr, "tp": entry - 3.0 * atr},
            )
        return StrategyIntent(
            strategy_id=self.manifest().strategy_id,
            strategy_version="1.0.0",
            config_revision="sandbox",
            instance_id="vol",
            action="HOLD",
            side="BUY",
            confidence=0.0,
            reason="no volume spike",
        )

    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
