"""Node base classes + helpers."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any, ClassVar

import pandas as pd


class ScoreNode(ABC):
    name:           ClassVar[str]
    label:          ClassVar[str]
    default_params: ClassVar[dict]
    param_schema:   ClassVar[dict]

    @abstractmethod
    def compute(self, ctx: "Any", params: dict) -> pd.Series:
        """returns Series indexed by ticker, 0..100 float."""


class GateNode(ABC):
    name:           ClassVar[str]
    label:          ClassVar[str]
    default_params: ClassVar[dict]
    param_schema:   ClassVar[dict]

    @abstractmethod
    def filter(self, ctx: "Any", params: dict) -> pd.Index:
        """returns surviving tickers."""


def percentile_rank(series: pd.Series) -> pd.Series:
    """Percentile rank in [0, 100]. All-equal → 50. NaN preserved."""
    if series.empty:
        return series.astype(float)
    if series.dropna().nunique() == 1:
        return pd.Series(50.0, index=series.index)
    ranked = series.rank(pct=True, na_option="keep") * 100.0
    return ranked
