"""Lightweight language detection using Unicode range heuristics.

No external dependencies. Detects: ru, en, zh, ja, ko, ar.
Returns "mixed" when no single script dominates, "unknown" for empty/short text.
"""

from __future__ import annotations

from typing import Literal

Language = Literal["ru", "en", "zh", "ja", "ko", "ar", "mixed", "unknown"]

# Unicode code-point ranges for script detection
_SCRIPT_RANGES: dict[str, list[tuple[int, int]]] = {
    "ru": [(0x0400, 0x04FF), (0x0500, 0x052F)],  # Cyrillic + supplement
    "zh": [(0x4E00, 0x9FFF), (0x3400, 0x4DBF)],  # CJK Unified + Extension A
    "ja": [(0x3040, 0x309F), (0x30A0, 0x30FF)],  # Hiragana + Katakana
    "ko": [(0xAC00, 0xD7AF), (0x1100, 0x11FF)],  # Hangul Syllables + Jamo
    "ar": [(0x0600, 0x06FF), (0x0750, 0x077F)],  # Arabic + supplement
}

_MIN_LENGTH = 3


def detect_language(text: str) -> Language:
    """Detect the primary language of text by Unicode character distribution.

    Counts alphabetic characters by script range.
    Latin characters map to "en".
    The dominant script (>=50% of letters) determines the language.
    """
    if not text or len(text.strip()) < _MIN_LENGTH:
        return "unknown"

    counts: dict[str, int] = {"latin": 0, "ru": 0, "zh": 0, "ja": 0, "ko": 0, "ar": 0}
    total = 0

    for ch in text:
        if not ch.isalpha():
            continue
        total += 1
        cp = ord(ch)

        matched = False
        for lang, ranges in _SCRIPT_RANGES.items():
            for lo, hi in ranges:
                if lo <= cp <= hi:
                    counts[lang] += 1
                    matched = True
                    break
            if matched:
                break

        if not matched and ch.isascii():
            counts["latin"] += 1

    if total == 0:
        return "unknown"

    max_lang = max(counts, key=lambda k: counts[k])
    max_count = counts[max_lang]
    ratio = max_count / total

    if ratio < 0.5:
        return "mixed"

    return "en" if max_lang == "latin" else max_lang  # type: ignore[return-value]
