"""
WNBA stats — uses nba_api with league_id='10'.

Kept self-contained (not a wrapper over NBA's stats.py) so the existing
NBA code path stays untouched. Shape of the returned dicts mirrors
stats.py so callers can dispatch on `sport` without branching downstream.
"""
from __future__ import annotations

import time
from datetime import datetime, timezone
from typing import Optional

from nba_api.stats.endpoints import playercareerstats, playergamelog
from nba_api.stats.static import players as wnba_players

from app.utils.cache import cache_get, cache_set
from app.config import (
    NBA_API_DELAY, NBA_API_TIMEOUT,
    SEASON_AVG_TTL, LAST_N_TTL,
)

WNBA_LEAGUE_ID = "10"
_STAT_MAP = {
    "PTS": "points",
    "REB": "rebounds",
    "AST": "assists",
    "FG3M": "threes",
    "BLK": "blocks",
    "STL": "steals",
    "TOV": "turnovers",
    "MIN": "minutes",
    "GP": "games_played",
}


def _wnba_current_season() -> str:
    now = datetime.now(timezone.utc)
    # WNBA season is roughly May–September; use the calendar year.
    return str(now.year)


def _safe(func, **kwargs):
    """Tiny rate-limited wrapper around nba_api endpoints."""
    time.sleep(NBA_API_DELAY)
    return func(timeout=NBA_API_TIMEOUT, **kwargs)


def _resolve_wnba_player(name: str) -> tuple[Optional[int], str]:
    name = (name or "").strip()
    if len(name) < 2:
        return None, ""
    # nba_api.static.players only ships NBA player lists; for WNBA we resolve
    # via the search endpoint (commonteamroster also works). For now we fall
    # back to a name match across the (NBA + WNBA) static set, then verify
    # with the live endpoint if needed.
    matches = wnba_players.find_players_by_full_name(name)
    if matches:
        return matches[0]["id"], matches[0]["full_name"]
    return None, ""


def _map_stats(row: dict) -> dict:
    return {our: row[their] for their, our in _STAT_MAP.items() if their in row}


def wnba_season_avg(player_name: str, stat_type: Optional[str] = None, season: Optional[str] = None) -> Optional[dict]:
    player_id, full_name = _resolve_wnba_player(player_name)
    if player_id is None:
        return None

    season = season or _wnba_current_season()
    cache_key = f"wnba:season:{player_id}:{season}"
    cached = cache_get(cache_key)
    if cached is not None:
        cached["source"] = "cache"
        if stat_type and stat_type in cached.get("stats", {}):
            cached["stats"] = {stat_type: cached["stats"][stat_type]}
        return cached

    career = _safe(
        playercareerstats.PlayerCareerStats,
        player_id=player_id,
        league_id_nullable=WNBA_LEAGUE_ID,
    )
    df = career.get_data_frames()[0]
    season_row = df[df["SEASON_ID"] == season]

    stats = _map_stats(season_row.iloc[0].to_dict()) if not season_row.empty else {}

    result = {
        "player": full_name,
        "player_id": player_id,
        "team": season_row.iloc[0]["TEAM_ABBREVIATION"] if not season_row.empty else "UNK",
        "season": season,
        "league": "wnba",
        "source": "live",
        "stats": stats,
    }
    cache_set(cache_key, result, SEASON_AVG_TTL)

    if stat_type and stat_type in stats:
        result["stats"] = {stat_type: stats[stat_type]}
    return result


def wnba_last_n(player_name: str, n: int = 10, stat_type: Optional[str] = None) -> Optional[dict]:
    player_id, full_name = _resolve_wnba_player(player_name)
    if player_id is None:
        return None

    n = min(max(int(n), 1), 30)
    cache_key = f"wnba:last:{player_id}:{n}"
    cached = cache_get(cache_key)
    if cached is not None:
        cached["source"] = "cache"
        if stat_type and stat_type in cached.get("stats", {}):
            cached["stats"] = {stat_type: cached["stats"][stat_type]}
        return cached

    season = _wnba_current_season()
    gamelog = _safe(
        playergamelog.PlayerGameLog,
        player_id=player_id,
        season=season,
        league_id_nullable=WNBA_LEAGUE_ID,
    )
    df = gamelog.get_data_frames()[0]

    if df.empty:
        return {
            "player": full_name,
            "player_id": player_id,
            "team": "UNK",
            "last_n": n,
            "league": "wnba",
            "source": "live",
            "stats": {},
        }

    recent = df.head(n)
    averages = {our: float(recent[their].mean()) for their, our in _STAT_MAP.items() if their in recent.columns}

    result = {
        "player": full_name,
        "player_id": player_id,
        "team": str(recent.iloc[0].get("MATCHUP", "")).split(" ")[0] or "UNK",
        "last_n": n,
        "league": "wnba",
        "source": "live",
        "stats": averages,
    }
    cache_set(cache_key, result, LAST_N_TTL)

    if stat_type and stat_type in averages:
        result["stats"] = {stat_type: averages[stat_type]}
    return result
