"""MACD 시그널선 크로스."""

from __future__ import annotations

import pandas as pd

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


class MacdCrossTechnique(BaseTechnique):
    """MACD가 시그널선을 상향 돌파 시 매수, 하향 돌파 시 매도."""

    technique_id = "macd_cross"
    technique_name = "MACD 크로스"
    category = "indicator"
    causal = True
    description = "MACD(12,26,9) 시그널선 골든·데드 크로스"

    def default_extra_params(self) -> dict:
        return {"fast": 12, "slow": 26, "signal": 9}

    def generate_signals(self, df: pd.DataFrame, params: TechniqueParams) -> list[TechniqueSignal]:
        fast = int(params.extra.get("fast", 12))
        slow = int(params.extra.get("slow", 26))
        signal_span = int(params.extra.get("signal", 9))

        close = df["close"].astype(float)
        macd_line, signal_line, _ = macd(close, fast=fast, slow=slow, signal=signal_span)

        signals: list[TechniqueSignal] = []
        start = slow + signal_span

        for i in range(start + 1, len(df)):
            if pd.isna(macd_line.iloc[i]) or pd.isna(signal_line.iloc[i]):
                continue

            prev_macd = float(macd_line.iloc[i - 1])
            prev_sig = float(signal_line.iloc[i - 1])
            curr_macd = float(macd_line.iloc[i])
            curr_sig = float(signal_line.iloc[i])
            price = float(close.iloc[i])
            dt = pd.Timestamp(df.iloc[i]["datetime"]).strftime("%Y-%m-%d %H:%M:%S")

            if prev_macd <= prev_sig and curr_macd > curr_sig:
                signals.append(
                    TechniqueSignal(
                        side="buy",
                        bar_index=i,
                        price=round(price, 2),
                        datetime=dt,
                        confidence=0.6,
                        reason="macd_bull_cross",
                    )
                )
            elif prev_macd >= prev_sig and curr_macd < curr_sig:
                signals.append(
                    TechniqueSignal(
                        side="sell",
                        bar_index=i,
                        price=round(price, 2),
                        datetime=dt,
                        confidence=0.6,
                        reason="macd_bear_cross",
                    )
                )

        return signals
