"""RS Rating — IBD 가중 (3m=2,6m=1,9m=1,12m=1)."""

import pandas as pd

from .base import ScoreNode, percentile_rank


_PERIOD_TO_DAYS = {"3m": 63, "6m": 126, "9m": 189, "12m": 252}


class RsRating(ScoreNode):
    name  = "rs_rating"
    label = "RS Rating (시장 대비 상대강도)"
    default_params = {"weights": {"3m": 2, "6m": 1, "9m": 1, "12m": 1}}
    param_schema = {
        "type": "object",
        "properties": {
            "weights": {"type": "object"}
        },
    }

    def compute(self, ctx, params: dict) -> pd.Series:
        weights: dict = params.get("weights", self.default_params["weights"])
        prices = ctx.prices
        kospi = ctx.kospi
        if prices.empty or kospi.empty:
            return pd.Series(dtype=float)

        ordered = prices.sort_values("date")

        def _excess_for_ticker(g: pd.DataFrame) -> float:
            closes = g.set_index("date")["close"]
            total = 0.0
            wsum = 0.0
            for period, w in weights.items():
                k = _PERIOD_TO_DAYS.get(period, 0)
                if len(closes) <= k or len(kospi) <= k:
                    continue
                r_stock = closes.iloc[-1] / closes.iloc[-(k + 1)] - 1
                r_market = kospi.iloc[-1] / kospi.iloc[-(k + 1)] - 1
                total += w * (r_stock - r_market)
                wsum += w
            return total / wsum if wsum else float("nan")

        raw = ordered.groupby("ticker", group_keys=False).apply(
            _excess_for_ticker, include_groups=False
        )
        return percentile_rank(raw).fillna(50.0)
