"""
Helpers for localized CSV template header labels (ES/EN) and alias registration.

csv_hint (opcional en cada columna TEMPLATE_COLUMNS): un dict o lista de dicts (orden importa).
- kind "enum_codes" + codes: lista corta (≤3) mostrada como "Base (a, b, c)" en descarga.
- kind "digits" + n: sufijo numérico, ES "(n dígitos)" / EN "(n digits)".
- kind "max_chars" + n: máximo caracteres (modelo / validadores CSV).
- kind "literal" + es / en: sufijo libre entre paréntesis por idioma.

cabeceras extendidas se registran en lookup de importación vía merge_download_header_into_lookup.
"""
from __future__ import annotations

from typing import Any, Callable, Dict, Iterator, Optional

CsvHintDict = Dict[str, Any]


def normalize_locale(locale: Optional[str]) -> str:
    if not locale:
        return "es"
    l = str(locale).lower().strip()
    if l.startswith("en"):
        return "en"
    return "es"


def display_header_for_locale(column: Dict[str, Any], locale: str) -> str:
    """
    Pick the CSV header cell for one column definition.
    Falls back to canonical when labels are absent.
    For ES: no usar labels.en antes que canonical — si solo existe labels.en (inyectado),
    sin labels.es el CSV en español debe seguir usando el nombre canónico (Clarion), no el EN.
    """
    loc = normalize_locale(locale)
    labels = column.get("labels")
    if isinstance(labels, dict):
        if loc == "en":
            return str(labels.get("en") or labels.get("es") or column.get("canonical") or "")
        return str(labels.get("es") or column.get("canonical") or labels.get("en") or "")
    return str(column.get("canonical") or "")


def _csv_hints_iter(column: Dict[str, Any]) -> Iterator[CsvHintDict]:
    """Siempre es generador (yield from ()) para filas sin csv_hint."""
    h = column.get("csv_hint")
    if h is None:
        yield from ()
        return
    if isinstance(h, list):
        for item in h:
            if isinstance(item, dict):
                yield item
    elif isinstance(h, dict):
        yield h


def _append_suffix(text: str, suffix_body: str) -> str:
    inner = suffix_body.strip()
    if not inner:
        return text
    return f"{text} ({inner})" if text else f"({inner})"


def _max_chars_suffix(n: int, locale: str) -> str:
    loc = normalize_locale(locale)
    if loc == "en":
        if n == 1:
            return "max. 1 character"
        return f"max. {n} characters"
    if n == 1:
        return "máx. 1 carácter"
    return f"máx. {n} caracteres"


def _apply_one_csv_hint(text: str, hint: CsvHintDict, locale: str) -> str:
    """Aplica un sufijo a la cabecera acumulada (display o ya con hints previos)."""
    loc = normalize_locale(locale)
    kind = hint.get("kind")
    if kind == "enum_codes":
        codes = hint.get("codes")
        if not isinstance(codes, list):
            return text
        if len(codes) == 0 or len(codes) > 3:
            return text
        inner = ", ".join(str(c) for c in codes)
        return _append_suffix(text, inner)
    if kind == "digits":
        n = hint.get("n")
        if n is None:
            return text
        try:
            ni = int(n)
        except (TypeError, ValueError):
            return text
        suf = f"{ni} digits" if loc == "en" else f"{ni} dígitos"
        return _append_suffix(text, suf)
    if kind == "max_chars":
        n = hint.get("n")
        if n is None:
            return text
        try:
            ni = int(n)
        except (TypeError, ValueError):
            return text
        if ni < 0:
            return text
        return _append_suffix(text, _max_chars_suffix(ni, loc))
    if kind == "literal":
        lit = hint.get("en") if loc == "en" else hint.get("es")
        if not lit and isinstance(hint.get("es"), str):
            lit = hint.get("es")
        if not lit and isinstance(hint.get("en"), str):
            lit = hint.get("en")
        if lit:
            return _append_suffix(text, str(lit))
        return text
    return text


def download_header_cell(column: Dict[str, Any], locale: Optional[str] = None) -> str:
    """
    Texto final de la celda de cabecera en plantilla descargada (incl. sufijos de ayuda).
    csv_hint puede ser un dict o lista de dicts (orden: p. ej. enum_codes luego max_chars).
    enum_codes solo si len(codes) ≤ 3.
    """
    loc = normalize_locale(locale)
    text = display_header_for_locale(column, loc)
    for hint in _csv_hints_iter(column):
        text = _apply_one_csv_hint(text, hint, loc)
    return text


def merge_download_header_into_lookup(
    item: Dict[str, Any],
    canonical: str,
    normalize_header_fn: Callable[[str], str],
    lookup: Dict[str, str],
) -> None:
    """Registra cabeceras de descarga ES/EN (con sufijos csv_hint) como alias del canonical."""
    for loc in ("es", "en"):
        cell = download_header_cell(item, loc)
        if cell:
            lookup[normalize_header_fn(cell)] = canonical


def merge_labels_into_lookup(
    item: Dict[str, Any],
    canonical: str,
    normalize_header_fn: Callable[[str], str],
    lookup: Dict[str, str],
) -> None:
    """Register labels.es / labels.en as extra normalized aliases for canonical."""
    labels = item.get("labels")
    if not isinstance(labels, dict):
        return
    for key in ("es", "en"):
        lab = labels.get(key)
        if lab:
            lookup[normalize_header_fn(str(lab))] = canonical
