"""
런타임 i18n 재번역 — 재시작 없이 언어 전환.

사용법:
    from ui.i18n_runtime import register, retranslate_all, set_language_and_retranslate

    label = QLabel(tr('label.foo'))
    register(label, 'label.foo')          # 약한 참조로 등록

    button = QPushButton()
    register(button, 'btn.bar', kwargs={'name': 'X'})

    # 그룹박스 제목 등 setter가 다른 경우
    register(group, 'group.work_time', setter='setTitle')

    # 윈도우 제목
    register(dialog, 'window.foo', setter='setWindowTitle')

언어 변경:
    set_language_and_retranslate('en')

각 widget은 weakref로 보관되므로 삭제되면 자동 정리. format placeholder가 있는
키는 kwargs를 함께 등록하면 retranslate 시 같은 인자로 재계산.
"""
from __future__ import annotations
import weakref
from typing import Any, Callable, List, Tuple, Optional

from core.i18n import tr, set_language as _set_language

# (weakref, key, setter_name, kwargs, post_format) 튜플 리스트
# weakref가 죽으면 다음 retranslate 시 정리.
_registry: List[Tuple[weakref.ReferenceType, str, str, dict, Optional[Callable]]] = []


def register(widget: Any, key: str, *, setter: str = 'setText',
             kwargs: Optional[dict] = None,
             post: Optional[Callable[[str], str]] = None) -> None:
    """위젯을 retranslate 대상으로 등록.

    Args:
        widget: PyQt 위젯 (setText/setTitle/setWindowTitle 등 지원)
        key: i18n 키
        setter: 호출할 메서드명 (기본 setText)
        kwargs: tr()에 전달할 format 인자 (정적인 경우만)
        post: 번역 후 한 번 더 가공할 콜백 — 예: 이모지 prefix
    """
    # 약한 참조 — 위젯 삭제 시 자동 GC
    try:
        ref = weakref.ref(widget)
    except TypeError:
        # weakref 미지원 객체는 retranslate 불가
        return
    _registry.append((ref, key, setter, kwargs or {}, post))
    # 초기 적용
    _apply(widget, key, setter, kwargs or {}, post)


def retranslate_all() -> None:
    """모든 등록된 위젯에 현재 언어로 텍스트 재적용."""
    global _registry
    alive = []
    for ref, key, setter, kw, post in _registry:
        widget = ref()
        if widget is None:
            continue  # 죽은 위젯은 빼버림
        try:
            _apply(widget, key, setter, kw, post)
            alive.append((ref, key, setter, kw, post))
        except RuntimeError:
            # Qt C++ 객체 삭제 후 호출 — 정리만 하고 패스
            continue
    _registry = alive


def set_language_and_retranslate(lang: str) -> None:
    """언어 전환 + 즉시 재번역."""
    _set_language(lang)
    retranslate_all()


def clear() -> None:
    """레지스트리 비우기 (테스트용)."""
    _registry.clear()


def _apply(widget: Any, key: str, setter: str, kw: dict,
            post: Optional[Callable[[str], str]]) -> None:
    text = tr(key, **kw)
    if post:
        text = post(text)
    fn = getattr(widget, setter, None)
    if callable(fn):
        fn(text)
