"""RSI 과매도·과매수 스윙."""

from __future__ import annotations

import pandas as pd

from deepcoin.techniques.base import BaseTechnique, TechniqueParams, TechniqueSignal
from deepcoin.techniques.indicators import rsi


class RsiSwingTechnique(BaseTechnique):
    """RSI 30 이탈 후 복귀 시 매수, 70 이탈 후 복귀 시 매도."""

    technique_id = "rsi_swing"
    technique_name = "RSI 스윙"
    category = "indicator"
    causal = True
    description = "RSI(14) 과매도 반등 매수·과매수 하락 매도"

    def default_extra_params(self) -> dict:
        return {"period": 14, "oversold": 30.0, "overbought": 70.0}

    def generate_signals(self, df: pd.DataFrame, params: TechniqueParams) -> list[TechniqueSignal]:
        period = int(params.extra.get("period", 14))
        oversold = float(params.extra.get("oversold", 30.0))
        overbought = float(params.extra.get("overbought", 70.0))

        close = df["close"].astype(float)
        rsi_vals = rsi(close, period=period)

        signals: list[TechniqueSignal] = []
        was_oversold = False
        was_overbought = False

        for i in range(period + 1, len(df)):
            if pd.isna(rsi_vals.iloc[i]):
                continue

            curr = float(rsi_vals.iloc[i])
            prev = float(rsi_vals.iloc[i - 1])
            price = float(close.iloc[i])
            dt = pd.Timestamp(df.iloc[i]["datetime"]).strftime("%Y-%m-%d %H:%M:%S")

            if curr < oversold:
                was_oversold = True
            if was_oversold and prev < oversold <= curr:
                signals.append(
                    TechniqueSignal(
                        side="buy",
                        bar_index=i,
                        price=round(price, 2),
                        datetime=dt,
                        confidence=0.65,
                        reason="rsi_oversold_exit",
                    )
                )
                was_oversold = False

            if curr > overbought:
                was_overbought = True
            if was_overbought and prev > overbought >= curr:
                signals.append(
                    TechniqueSignal(
                        side="sell",
                        bar_index=i,
                        price=round(price, 2),
                        datetime=dt,
                        confidence=0.65,
                        reason="rsi_overbought_exit",
                    )
                )
                was_overbought = False

        return signals
