"""Pure cross-sectional crypto PRICE/VOLUME factor scores on the crypto_pit panel
{sym:{day:(close, qvol, funding)}}. Each returns {symbol: score} aligned to `eligible`
(robust_z across peers; higher score = stronger long). No I/O."""
from __future__ import annotations

from fxhnt.domain.cross_sectional_funding import Panel
from fxhnt.domain.strategies.equity_factor import realized_vol_from_closes, robust_z


def xs_reversal_score(panel: Panel, eligible: list[str], asof_day: int, lookback: int = 3) -> dict[str, float]:
    """Short-term reversal: long recent LOSERS. score = robust_z(-recent_return).
    recent_return = close[asof]/close[asof-lookback]-1 using the nearest bars <= asof."""
    vals: list[float | None] = []
    for s in eligible:
        days = sorted(d for d in panel[s] if d <= asof_day)
        # need a bar at/near asof and one ~lookback before
        if len(days) < 2:
            vals.append(None)
            continue
        c_now = panel[s][days[-1]][0]
        prior = [d for d in days if d <= asof_day - lookback]
        if not prior or c_now <= 0:
            vals.append(None)
            continue
        c_then = panel[s][prior[-1]][0]
        vals.append(-(c_now / c_then - 1.0) if c_then > 0 else None)
    z = robust_z(vals)
    return {eligible[i]: z[i] for i in range(len(eligible))}


def xs_lowvol_score(panel: Panel, eligible: list[str], asof_day: int, window: int = 30) -> dict[str, float]:
    """Low-volatility: long LOW-vol coins. score = robust_z(-trailing_realized_vol)."""
    vals: list[float | None] = []
    for s in eligible:
        closes = [panel[s][d][0] for d in sorted(panel[s]) if d <= asof_day]
        v = realized_vol_from_closes(closes, window=window)
        vals.append(-v if v is not None else None)
    z = robust_z(vals)
    return {eligible[i]: z[i] for i in range(len(eligible))}


def xs_illiquidity_score(panel: Panel, eligible: list[str], asof_day: int, window: int = 30) -> dict[str, float]:
    """Illiquidity premium: long LOW dollar-volume coins. score = robust_z(-trailing_mean_qvol).
    (Flagged cost-fragile — the long leg is thin coins.)"""
    lo = asof_day - window
    vals: list[float | None] = []
    for s in eligible:
        qv = [panel[s][d][1] for d in panel[s] if lo < d <= asof_day]
        vals.append(-(sum(qv) / len(qv)) if qv else None)
    z = robust_z(vals)
    return {eligible[i]: z[i] for i in range(len(eligible))}
