"""Coeficiente de correlacion de Spearman (correlacion de rangos)."""

import math

from scipy.stats import spearmanr


def spearman_corr(xs: list, ys: list) -> float:
    """Coeficiente de correlacion de Spearman entre dos listas pareadas.

    La correlacion de rangos capta relaciones monotonicas (no necesariamente
    lineales) entre dos variables. Es robusta frente a outliers y a relaciones
    curvas siempre que sean monotonas.

    Descarta los pares en los que cualquiera de los dos valores sea None, NaN
    o no numerico. Si tras la limpieza quedan menos de 3 pares validos, o la
    varianza de alguna de las dos series es cero, devuelve 0.0.

    Args:
        xs: lista de valores numericos de la primera variable.
        ys: lista de valores numericos de la segunda variable, pareada con xs.

    Returns:
        coeficiente de Spearman en rango [-1, 1] como float. Nunca None ni
        excepcion: ante datos insuficientes o degenerados devuelve 0.0.
    """

    def _is_num(v) -> bool:
        return isinstance(v, (int, float)) and not isinstance(v, bool) and not (
            isinstance(v, float) and math.isnan(v)
        )

    pairs = [
        (float(x), float(y))
        for x, y in zip(xs, ys)
        if _is_num(x) and _is_num(y)
    ]

    if len(pairs) < 3:
        return 0.0

    clean_x = [p[0] for p in pairs]
    clean_y = [p[1] for p in pairs]

    # Varianza cero en cualquiera de las series => correlacion indefinida.
    if len(set(clean_x)) < 2 or len(set(clean_y)) < 2:
        return 0.0

    corr = spearmanr(clean_x, clean_y).statistic

    if corr is None or math.isnan(float(corr)):
        return 0.0

    return float(corr)
