# src/strategies/mean_reversion.py

import pandas as pd
import numpy as np

from src.strategies.base import Strategy
from src.core.strategy import Signal


class RSIMeanReversion(Strategy):
    """
    Estrategia de reversión a la media basada en RSI.

    Idea:
    - Compra cuando el mercado está sobrevendido
    - Vende cuando el precio rebota hacia la media

    Señales:
    - BUY: RSI cruza por debajo de oversold
    - SELL: RSI cruza por encima de overbought
    - HOLD: en cualquier otro caso

    Parámetros:
        period: periodo del RSI
        oversold: nivel de sobreventa
        overbought: nivel de sobrecompra

    Valores típicos:
        period = 14
        oversold = 30
        overbought = 70
    """

    def __init__(
        self,
        period: int = 14,
        oversold: float = 30.0,
        overbought: float = 70.0,
    ):
        super().__init__(
            name="RSI_MeanReversion",
            params={
                "period": period,
                "oversold": oversold,
                "overbought": overbought,
            },
        )

        self.period = period
        self.oversold = oversold
        self.overbought = overbought

    # --------------------------------------------------
    def init_indicators(self, data: pd.DataFrame) -> pd.DataFrame:
        """
        Calcula el RSI clásico (Wilder).

        Añade:
            - data["rsi"]
        """
        delta = data["close"].diff()

        gain = delta.clip(lower=0)
        loss = -delta.clip(upper=0)

        avg_gain = gain.ewm(alpha=1 / self.period, adjust=False).mean()
        avg_loss = loss.ewm(alpha=1 / self.period, adjust=False).mean()

        rs = avg_gain / avg_loss
        rsi = 100 - (100 / (1 + rs))

        data["rsi"] = rsi

        return data

    # --------------------------------------------------
    def generate_signal(self, idx: int) -> Signal:
        """
        Genera señales de trading basadas en cruces del RSI.
        """
        if idx == 0:
            return Signal.HOLD

        rsi_prev = self.data["rsi"].iloc[idx - 1]
        rsi_curr = self.data["rsi"].iloc[idx]

        # BUY → cruce hacia abajo de oversold
        if rsi_prev > self.oversold and rsi_curr <= self.oversold:
            return Signal.BUY

        # SELL → cruce hacia arriba de overbought
        if rsi_prev < self.overbought and rsi_curr >= self.overbought:
            return Signal.SELL

        return Signal.HOLD
