"""Technical indicators: SMA, EMA, RSI, MACD."""

from __future__ import annotations

from typing import Any, List

try:
    import pandas as pd
    _HAS_PANDAS = True
except ImportError:
    _HAS_PANDAS = False

import math


# ── Simple Moving Average ──────────────────────────────────────────────────

def sma(series: "pd.Series", window: int) -> "pd.Series":
    """Simple Moving Average.

    Parameters
    ----------
    series : pd.Series
        Price series (e.g. close prices).
    window : int
        Lookback window in bars.

    Returns
    -------
    pd.Series
        SMA series of the same length (NaN for the first ``window-1`` values).
    """
    if not _HAS_PANDAS:
        raise ImportError("pandas is required for analysis functions")
    return series.rolling(window=window, min_periods=1).mean()


def ema(series: "pd.Series", span: int) -> "pd.Series":
    """Exponential Moving Average.

    Parameters
    ----------
    series : pd.Series
        Price series.
    span : int
        EMA span (comparable to an SMA window).

    Returns
    -------
    pd.Series
        EMA series.
    """
    if not _HAS_PANDAS:
        raise ImportError("pandas is required for analysis functions")
    return series.ewm(span=span, adjust=False).mean()


# ── RSI ───────────────────────────────────────────────────────────────────

def rsi(series: "pd.Series", period: int = 14) -> "pd.Series":
    """Relative Strength Index.

    Parameters
    ----------
    series : pd.Series
        Close price series.
    period : int
        RSI period (default: 14).

    Returns
    -------
    pd.Series
        RSI values in [0, 100].
    """
    if not _HAS_PANDAS:
        raise ImportError("pandas is required for analysis functions")
    delta = series.diff()
    gain = delta.clip(lower=0)
    loss = -delta.clip(upper=0)
    avg_gain = gain.rolling(window=period, min_periods=period).mean()
    avg_loss = loss.rolling(window=period, min_periods=period).mean()
    rs = avg_gain / avg_loss
    return 100 - (100 / (1 + rs))


# ── MACD ─────────────────────────────────────────────────────────────────

def macd(
    series: "pd.Series",
    fast: int = 12,
    slow: int = 26,
    signal: int = 9,
) -> tuple["pd.Series", "pd.Series", "pd.Series"]:
    """MACD (Moving Average Convergence Divergence).

    Parameters
    ----------
    series : pd.Series
        Close price series.
    fast : int
        Fast EMA span (default: 12).
    slow : int
        Slow EMA span (default: 26).
    signal : int
        Signal line EMA span (default: 9).

    Returns
    -------
    tuple[pd.Series, pd.Series, pd.Series]
        (macd_line, signal_line, histogram).
    """
    if not _HAS_PANDAS:
        raise ImportError("pandas is required for analysis functions")
    ema_fast = ema(series, fast)
    ema_slow = ema(series, slow)
    macd_line = ema_fast - ema_slow
    signal_line = ema(macd_line, signal)
    histogram = macd_line - signal_line
    return macd_line, signal_line, histogram
