"""i18n - lightweight interface translations (EN source of truth,
translations for every language in SUPPORTED, see i18n_strings/).

Deliberately NOT Qt Linguist (.ts/.qm): no extra build-toolchain step, fully
deterministic inside the Nuitka frozen build, and live-switchable at runtime.

Usage (Python):   from services.i18n import t; t("upd_available", version="1.4")
Usage (QML):      AppBridge.tr.settings_title   (re-evaluates on trChanged)

Rules:
* EN is the source of truth and the fallback for any missing key.
* User content (custom mode names, typed text) is never translated.
* Log messages stay English — they are not user-visible.
"""
from __future__ import annotations

from loguru import logger

from .i18n_strings import TABLES

DEFAULT_LANGUAGE = "en"
# Order = display order in Settings; "en" must stay first (fallback source).
SUPPORTED = tuple(TABLES)

STRINGS: dict[str, dict[str, str]] = TABLES
_EN = STRINGS["en"]


def builtin_mode_display_name(mode_id: str, stored_name: str) -> str:
    """Localized display name for an AI mode.

    Built-in modes are persisted with their English default name; as long as
    the user hasn't renamed one (stored name equals the default in ANY
    language, so a once-persisted localized name stays live-switchable), the
    menu shows the current UI language. Custom modes and renamed built-ins
    show the stored name verbatim."""
    key = f"mode_{mode_id}"
    variants = {tbl[key] for tbl in STRINGS.values() if key in tbl}
    if not variants:
        return stored_name
    if not stored_name or stored_name in variants:
        return t(key)
    return stored_name

_current = DEFAULT_LANGUAGE


# Windows primary language ids (LANGID & 0xFF) → our UI language codes.
_WIN_PRIMARY_LANG = {
    0x07: "de",  # LANG_GERMAN
    0x0A: "es",  # LANG_SPANISH
    0x0C: "fr",  # LANG_FRENCH
    0x10: "it",  # LANG_ITALIAN
    0x16: "pt",  # LANG_PORTUGUESE
    0x13: "nl",  # LANG_DUTCH
    0x15: "pl",  # LANG_POLISH
    0x1F: "tr",  # LANG_TURKISH
    0x19: "ru",  # LANG_RUSSIAN
    0x04: "zh",  # LANG_CHINESE
    0x11: "ja",  # LANG_JAPANESE
    0x12: "ko",  # LANG_KOREAN
}

# Native display names for the Settings language picker (never translated —
# every user must be able to recognise their own language).
NATIVE_NAMES = {
    "en": "English", "de": "Deutsch", "es": "Español", "fr": "Français",
    "it": "Italiano", "pt": "Português", "nl": "Nederlands", "pl": "Polski",
    "tr": "Türkçe", "ru": "Русский", "zh": "中文", "ja": "日本語", "ko": "한국어",
}


def system_language() -> str:
    """Best-effort OS display language, mapped to a supported UI language."""
    try:
        import ctypes

        lang_id = ctypes.windll.kernel32.GetUserDefaultUILanguage()
        mapped = _WIN_PRIMARY_LANG.get(lang_id & 0xFF)
        if mapped in SUPPORTED:
            return mapped
    except Exception:
        pass
    return DEFAULT_LANGUAGE


def resolve_language(pref: str | None) -> str:
    """Map the stored preference to a concrete language ('' = auto/OS)."""
    pref = (pref or "").strip().lower()
    if pref in SUPPORTED:
        return pref
    return system_language()


def set_language(lang: str) -> None:
    global _current
    _current = lang if lang in SUPPORTED else DEFAULT_LANGUAGE


def current_language() -> str:
    return _current


def t(key: str, **fmt: object) -> str:
    """Translate a key in the current language (EN fallback, format-safe)."""
    table = STRINGS.get(_current, _EN)
    text = table.get(key) or _EN.get(key)
    if text is None:
        logger.warning("i18n: missing key {!r}", key)
        return key
    if fmt:
        try:
            return text.format(**fmt)
        except (KeyError, IndexError) as e:
            logger.warning("i18n: bad format for {!r}: {}", key, e)
            return text
    return text


def table_for_qml() -> dict[str, str]:
    """Merged table for the QML bridge property (current over EN fallback)."""
    merged = dict(_EN)
    if _current != "en":
        merged.update(STRINGS.get(_current, {}))
    return merged
