"""
Heuristics for spoken language preference (English / Hindi / Kannada) on MCube calls.

Used by ws_bridge and ai_worker: explicit phrases, then Indic script, else STT default.
"""

from __future__ import annotations

import re
from typing import Optional

# Devanagari (Hindi, etc.) vs Kannada script blocks (must not treat Latin "hi" as Hindi).
_DEVANAGARI_RE = re.compile(r"[\u0900-\u097F]")
_KANNADA_RE = re.compile(r"[\u0C80-\u0CFF]")

# Explicit spoken preference (avoid matching greeting "hi" as Hindi).
_PREF_EN = re.compile(
    r"\b("
    r"english|inglish|"
    r"in\s+english|speak\s+english|talk\s+in\s+english|english\s+please|please\s+english"
    r")\b",
    re.IGNORECASE,
)
_PREF_HI = re.compile(
    r"\b("
    r"hindi|hinglish|hindustani|"
    r"in\s+hindi|speak\s+hindi|talk\s+in\s+hindi|hindi\s+please|please\s+hindi|"
    r"hindi\s+mein|hindi\s+bolo|hindi\s+mein\s+bolo"
    r")\b",
    re.IGNORECASE,
)
_PREF_KN = re.compile(
    r"\b("
    r"kannada|canara|"
    r"in\s+kannada|speak\s+kannada|talk\s+in\s+kannada|kannada\s+please|please\s+kannada"
    r")\b|ಕನ್ನಡ",
    re.IGNORECASE,
)


def _only_greeting_latin(text: str) -> bool:
    low = text.strip().lower()
    if not low:
        return True
    tokens = set(re.findall(r"[a-zA-Z']+", low))
    return bool(tokens) and tokens <= {"hello", "hi", "hey"}


def _stt_base(stt_default: str) -> str:
    s = (stt_default or "en").strip().lower()
    if not s:
        return "en"
    primary = s.split("-", 1)[0].split("_", 1)[0]
    if primary in ("en", "hi", "kn"):
        return primary
    if primary == "hin":
        return "hi"
    if primary in ("kan", "kn"):
        return "kn"
    if primary in ("eng",):
        return "en"
    return "en"


def detect_language_preference(text: str) -> Optional[str]:
    """
    If the caller clearly asks for English, Hindi, or Kannada, return that code.
    Returns None when there is no explicit preference (including lone 'hi' / 'hello' greetings).
    """
    if not text or not text.strip():
        return None
    raw = text.strip()
    if _only_greeting_latin(raw) and not _KANNADA_RE.search(raw) and not _DEVANAGARI_RE.search(raw):
        return None
    if _PREF_KN.search(raw):
        return "kn"
    if _PREF_HI.search(raw):
        return "hi"
    if _PREF_EN.search(raw):
        return "en"
    # One-word / noisy STT answers (no word-boundary "hindi" substring, e.g. glued tokens).
    letters_only = re.sub(r"[^a-z]", "", raw.lower())
    if letters_only:
        if letters_only in {
            "hindi",
            "hindhi",
            "hindee",
            "hinthi",
            "hinglish",
            "hindustani",
            "hindy",
            "hendi",
            "hindii",
            "hindii",
            "hinidi",
            "hind",
        }:
            return "hi"
        if letters_only in {"english", "inglish"}:
            return "en"
        if letters_only in {"kannada", "kanada"}:
            return "kn"
    return None


def resolve_detected_language(stt_default: str, user_text: str) -> str:
    """
    Merge STT default with explicit preference, then Indic script, else canonical STT base.
    """
    base = _stt_base(stt_default)
    t = user_text or ""
    pref = detect_language_preference(t)
    if pref:
        return pref
    if _KANNADA_RE.search(t):
        return "kn"
    if _DEVANAGARI_RE.search(t):
        return "hi"
    return base