"""Couche logique de l'éditeur de profils (persistance via profile_defaults).

Wrappers testables sans display : assemblage de la spec, détection
runtime/éditable vs defaut/lecture-seule, sauvegarde dans config/profiles.yml.
Aucun profil par défaut (profiles.default.yml) n'est jamais modifié ici.
"""

from __future__ import annotations

from pathlib import Path
from typing import Any, Iterable, Optional

from profile_defaults import (
    delete_runtime_profile,
    get_default_profile_key,
    list_effective_profiles,
    load_runtime_profiles_overlay_dict,
    save_runtime_profile,
    set_runtime_default_profile,
)


def _clean_list(values: Optional[Iterable]) -> list[str]:
    return [str(v).strip() for v in (values or []) if str(v).strip()]


def build_profile_spec(
    *,
    label: str,
    description: str = "",
    require_manual_mask: bool = False,
    force_disable_vlm: bool = False,
    preferred_manual_mask_template: str = "",
    whitelist: Optional[Iterable] = None,
    blacklist: Optional[Iterable] = None,
    stopwords: Optional[Iterable] = None,
) -> dict[str, Any]:
    """Assemble une spec de profil persistable (3 listes normalisées)."""
    return {
        "label": str(label or "").strip(),
        "description": str(description or ""),
        "require_manual_mask": bool(require_manual_mask),
        "force_disable_vlm": bool(force_disable_vlm),
        "preferred_manual_mask_template": str(preferred_manual_mask_template or "").strip(),
        "has_preferred_manual_mask_template": True,
        "has_param_lists": True,
        "param_lists": {
            "whitelist_phrases": _clean_list(whitelist),
            "blacklist_force_mask_terms": _clean_list(blacklist),
            "additional_stopwords": _clean_list(stopwords),
        },
    }


def runtime_profile_keys(path: Path | None = None) -> set[str]:
    """Clés des profils définis dans l'overlay runtime (config/profiles.yml)."""
    try:
        data = load_runtime_profiles_overlay_dict(path) or {}
    except Exception:
        return set()
    profiles = data.get("profiles") if isinstance(data, dict) else None
    return set(profiles) if isinstance(profiles, dict) else set()


def profile_is_editable(key: str, path: Path | None = None) -> bool:
    """Un profil est éditable s'il est dans l'overlay runtime (pas un defaut pur)."""
    return key in runtime_profile_keys(path)


def _default_key(path: Path | None = None) -> Optional[str]:
    try:
        data = load_runtime_profiles_overlay_dict(path) or {}
        if isinstance(data, dict) and data.get("default_profile"):
            return str(data["default_profile"])
    except Exception:
        pass
    try:
        return get_default_profile_key()
    except Exception:
        return None


def list_profile_choices(path: Path | None = None) -> list[dict]:
    """Liste triée des profils avec méta : ``key``, ``label``, ``editable``, ``is_default``."""
    profiles = list_effective_profiles(path)
    runtime = runtime_profile_keys(path)
    default = _default_key(path)
    return [
        {
            "key": key,
            "label": str(profiles[key].get("label") or key),
            "editable": key in runtime,
            "is_default": key == default,
        }
        for key in sorted(profiles)
    ]


def slug_for_copy(key: str, existing: Iterable[str]) -> str:
    """Clé de copie unique : ``{key}_copie`` puis ``_2``, ``_3``…"""
    existing = set(existing)
    base = f"{key}_copie"
    if base not in existing:
        return base
    index = 2
    while f"{base}_{index}" in existing:
        index += 1
    return f"{base}_{index}"


def save_profile(key: str, spec: dict, path: Path | None = None, *, set_default: bool = False) -> Path:
    return save_runtime_profile(key, spec, path, set_default=set_default)


def set_default_profile(key: str, path: Path | None = None) -> Path:
    return set_runtime_default_profile(key, path)


def delete_profile(key: str, path: Path | None = None) -> Path:
    return delete_runtime_profile(key, path)
