from __future__ import annotations

from collections import deque
from decimal import Decimal

from .models import Candle, OrderSide, Signal, SignalType


class SmaCrossoverStrategy:
    def __init__(self, fast_window: int, slow_window: int) -> None:
        if fast_window <= 0 or slow_window <= 0:
            raise ValueError("SMA windows must be positive")
        if fast_window >= slow_window:
            raise ValueError("fast_window must be less than slow_window")
        self.fast_window = fast_window
        self.slow_window = slow_window
        self._closes: deque[Decimal] = deque(maxlen=slow_window)
        self._previous_relation: int | None = None

    def on_candle(self, candle: Candle) -> Signal:
        self._closes.append(candle.close)
        if len(self._closes) < self.slow_window:
            return Signal(
                candle.symbol,
                SignalType.HOLD,
                None,
                "not enough candle history",
                created_at_ms=candle.close_time,
            )

        closes = list(self._closes)
        fast = sum(closes[-self.fast_window :]) / Decimal(self.fast_window)
        slow = sum(closes[-self.slow_window :]) / Decimal(self.slow_window)
        relation = 1 if fast > slow else -1 if fast < slow else 0

        previous = self._previous_relation
        self._previous_relation = relation

        if previous is not None and previous <= 0 and relation > 0:
            return Signal(
                candle.symbol,
                SignalType.BUY,
                OrderSide.BUY,
                f"fast SMA crossed above slow SMA: {fast} > {slow}",
                created_at_ms=candle.close_time,
            )
        if previous is not None and previous >= 0 and relation < 0:
            return Signal(
                candle.symbol,
                SignalType.SELL,
                OrderSide.SELL,
                f"fast SMA crossed below slow SMA: {fast} < {slow}",
                created_at_ms=candle.close_time,
            )
        return Signal(
            candle.symbol,
            SignalType.HOLD,
            None,
            "no crossover",
            created_at_ms=candle.close_time,
        )
