"""Chargement en mémoire du catalogue statique des scénarios."""

import json
import random
from copy import deepcopy
from pathlib import Path
from typing import Any, Optional


SCENARIOS_FILE = Path(__file__).resolve().parent / "data" / "scenarios.json"


def _load_scenarios() -> list[dict[str, Any]]:
    with SCENARIOS_FILE.open("r", encoding="utf-8") as scenarios_file:
        scenarios = json.load(scenarios_file)

    if not isinstance(scenarios, list):
        raise ValueError(f"Le catalogue {SCENARIOS_FILE} doit contenir une liste.")

    required_fields = {
        "slug",
        "title",
        "pitch",
        "teams_setup",
        "objectifs_victory",
        "specific_rules",
        "respawn_rules",
        "app_usage",
        "map_markers",
    }
    for index, scenario in enumerate(scenarios, start=1):
        if not isinstance(scenario, dict) or not required_fields.issubset(scenario):
            raise ValueError(f"Le scénario #{index} ne respecte pas la structure attendue.")

    return scenarios


# Chargement à l'import du module, au démarrage de l'application.
_SCENARIOS = _load_scenarios()


def _is_app_required(scenario: dict[str, Any]) -> bool:
    app_usage = scenario.get("app_usage")
    if not isinstance(app_usage, dict):
        return False

    phones = str(app_usage.get("required_phones", "")).strip().lower().rstrip(".")
    details = str(app_usage.get("details", "")).strip().lower().rstrip(".")
    if phones in {"aucun", "aucune", "non", "none", "0", ""}:
        return False
    if details in {"aucun", "aucune", "non", "none", "sans"}:
        return False
    return True


def _scenario_for_api(index: int, scenario: dict[str, Any]) -> dict[str, Any]:
    """Expose les métadonnées dérivées dont les templates avaient besoin en BDD."""
    result = deepcopy(scenario)
    result["id"] = index
    result["is_app_required"] = _is_app_required(scenario)
    return result


def get_all_scenarios() -> list[dict[str, Any]]:
    """Retourne les scénarios dans l'ordre du fichier, avec leurs champs dérivés."""
    return [_scenario_for_api(index, scenario) for index, scenario in enumerate(_SCENARIOS, start=1)]


def get_scenario_by_slug_or_id(id_or_slug: Any) -> Optional[dict[str, Any]]:
    """Recherche un scénario par slug ou par son identifiant ordinal historique."""
    value = str(id_or_slug).strip()
    for index, scenario in enumerate(_SCENARIOS, start=1):
        if scenario.get("slug") == value:
            return _scenario_for_api(index, scenario)

    if value.isdigit():
        index = int(value)
        if 1 <= index <= len(_SCENARIOS):
            return _scenario_for_api(index, _SCENARIOS[index - 1])
    return None


def get_random_scenario(app_required: Optional[bool] = None) -> Optional[dict[str, Any]]:
    """Retourne un scénario au hasard, avec un filtre optionnel sur l'application."""
    scenarios = get_all_scenarios()
    if app_required is not None:
        scenarios = [scenario for scenario in scenarios if scenario["is_app_required"] is app_required]
    return random.choice(scenarios) if scenarios else None
