"""Translation helpers and language-aware mixins."""

from __future__ import annotations

import contextlib
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Dict

try:  # Python 3.11+
    import tomllib  # type: ignore[attr-defined]
except ModuleNotFoundError:  # pragma: no cover - fallback
    with contextlib.suppress(ModuleNotFoundError):
        import tomli as tomllib  # type: ignore[assignment]
    if "tomllib" not in globals():
        tomllib = None  # type: ignore[assignment]


LANG_DIR = Path(__file__).resolve().parent / "lang"
FALLBACK_LANGUAGE = "en"


def _available_language_files() -> Dict[str, Path]:
    files: Dict[str, Path] = {}
    if LANG_DIR.exists():
        for path in LANG_DIR.glob("*.toml"):
            files[path.stem.lower()] = path
    return files


def _load_translations(lang: str) -> Dict[str, str]:
    if tomllib is None:
        return {}
    lang_files = _available_language_files()
    path = lang_files.get(lang.lower())
    if path is None:
        return {}
    try:
        with path.open("rb") as handle:
            data = tomllib.load(handle)
    except (OSError, AttributeError, ValueError, TypeError):  # type: ignore[arg-type]
        return {}
    translations = data.get("translations")
    if not isinstance(translations, dict):
        return {}
    out: Dict[str, str] = {}
    for key, value in translations.items():
        if isinstance(key, str) and isinstance(value, str):
            out[key] = value
    return out


@dataclass
class Translator:
    """Simple lookup-based translator with file-backed dictionaries."""

    language: str = FALLBACK_LANGUAGE
    _translations: Dict[str, str] = field(default_factory=dict, init=False)
    _fallback: Dict[str, str] = field(default_factory=dict, init=False)

    def __post_init__(self) -> None:
        self._fallback = _load_translations(FALLBACK_LANGUAGE)
        self.set_language(self.language)

    def set_language(self, language: str) -> None:
        chosen = language.lower()
        data = _load_translations(chosen)
        if not data:
            chosen = FALLBACK_LANGUAGE
            data = _load_translations(FALLBACK_LANGUAGE)
        self.language = chosen
        self._translations = data or {}

    def translate(self, key: str, **values: Any) -> str:
        template = self._translations.get(key) or self._fallback.get(key) or key
        if values:
            try:
                return template.format(**values)
            except (KeyError, ValueError):
                return template
        return template


class I18nMixin:
    """Mixin providing translated text helpers."""

    language: str
    translator: Translator

    def init_i18n(self, language: str | None = None) -> None:
        self.translator = Translator()
        self.set_language(language or FALLBACK_LANGUAGE)

    def set_language(self, language: str) -> None:
        self.translator.set_language(language)
        self.language = self.translator.language

    def _t(self, key: str, **values: Any) -> str:
        return self.translator.translate(key, **values)

    @property
    def available_languages(self) -> tuple[str, ...]:
        return tuple(sorted(_available_language_files().keys()))


__all__ = ["I18nMixin", "Translator", "LANG_DIR", "FALLBACK_LANGUAGE"]
