from __future__ import annotations

import pandas as pd


RETURN_WINDOWS = (1, 2, 3, 5, 10, 20, 60)
SMA_WINDOWS = (5, 10, 20, 50, 100, 200)
EMA_WINDOWS = (9, 20, 50)


def add_price_features(group: pd.DataFrame) -> pd.DataFrame:
    result = group.sort_values("date").copy()
    close = result["adjusted_close"].fillna(result["close"])
    for window in RETURN_WINDOWS:
        result[f"return_{window}d"] = close.pct_change(window, fill_method=None)
    result["momentum_acceleration_5d"] = result["return_5d"] - result["return_5d"].shift(5)
    for window in SMA_WINDOWS:
        sma = close.rolling(window, min_periods=window).mean()
        result[f"sma_{window}"] = sma
        result[f"close_sma_{window}_ratio"] = close / sma
        result[f"sma_{window}_slope_5d"] = sma.pct_change(5, fill_method=None)
    for window in EMA_WINDOWS:
        ema = close.ewm(span=window, adjust=False, min_periods=window).mean()
        result[f"ema_{window}"] = ema
        result[f"close_ema_{window}_ratio"] = close / ema
    result["sma_20_50_ratio"] = result["sma_20"] / result["sma_50"]
    result["sma_50_200_ratio"] = result["sma_50"] / result["sma_200"]
    previous_close = result["close"].shift(1)
    result["gap_previous_close"] = result["open"] / previous_close - 1
    for window, label in ((20, "20d"), (50, "50d"), (252, "52w")):
        high = result["high"].rolling(window, min_periods=window).max()
        low = result["low"].rolling(window, min_periods=window).min()
        result[f"distance_{label}_high"] = close / high - 1
        result[f"distance_{label}_low"] = close / low - 1
        result[f"breakout_{label}_high"] = (close >= high.shift(1)).astype("float").where(high.shift(1).notna())
    return result

