# -*- coding: utf-8 -*-
"""
Darwin-60B-DUO Router — language + domain + complexity classification.

Returns a RouteDecision indicating which Hybrid-A strategy to invoke:
  - "route_darwin"           : English-only single backend
  - "route_awaxis"           : Korean-only single backend
  - "split_refine"           : Darwin reasons → AWAXIS polishes (Korean output, English reasoning)
  - "split_refine_reverse"   : AWAXIS retrieves → Darwin polishes (English output, Korean context)
  - "ensemble_v1"            : MCQ / short answer requiring cross-verification
"""
import re
from dataclasses import dataclass
from typing import Optional


# ---------------------------------------------------------------------------
# Heuristic keyword lists
# ---------------------------------------------------------------------------
ENGLISH_REASONING_KEYWORDS = {
    # Math
    "prove", "theorem", "derivative", "integral", "equation", "matrix",
    "vector", "topology", "manifold",
    # Code
    "def ", "function ", "import ", "class ", "return ", "lambda ",
    "javascript", "python", "rust", "golang", "typescript", "regex",
    # Sci-tech
    "gradient", "tensor", "embedding", "transformer", "attention",
    "rlhf", "rlvr", "quantization", "kernel",
    # Markers
    r"\\boxed", r"\\frac", r"\\sum", r"\\int", "<eqn>", "$$",
}

KOREAN_CULTURAL_KEYWORDS = {
    "추석", "설날", "한국", "조선", "고려", "신라", "백제",
    "k-pop", "케이팝", "한복", "김치", "한국어",
    "공무원", "정부", "과기부", "교육부", "외교부",
    "국회", "정책", "법안", "조례",
}

MCQ_PATTERNS = [
    r"\(A\).*\(B\).*\(C\).*\(D\)",
    r"^\s*A\..*\n\s*B\..*\n\s*C\.",
    r"answer.*[A-D]",
    r"정답.*[ABCD가나다라]",
    r"\bANSWER:",
]


@dataclass
class RouteDecision:
    strategy: str
    reason: str
    korean_ratio: float = 0.0
    english_ratio: float = 0.0
    has_reasoning_marker: bool = False
    has_korean_cultural_marker: bool = False
    is_mcq: bool = False


# ---------------------------------------------------------------------------
# Detection primitives
# ---------------------------------------------------------------------------
def korean_ratio(text: str) -> float:
    """Fraction of Hangul characters."""
    if not text:
        return 0.0
    total = len(text)
    hangul = len(re.findall(r"[가-힣]", text))
    return hangul / total if total > 0 else 0.0


def english_ratio(text: str) -> float:
    """Fraction of ASCII alphabetic characters."""
    if not text:
        return 0.0
    total = len(text)
    alpha = len(re.findall(r"[a-zA-Z]", text))
    return alpha / total if total > 0 else 0.0


def has_reasoning_marker(text: str) -> bool:
    """English STEM / coding keywords or math markers."""
    lower = text.lower()
    for kw in ENGLISH_REASONING_KEYWORDS:
        # Some keywords are regex patterns (start with backslash)
        if kw.startswith("\\"):
            if re.search(re.escape(kw), text):
                return True
        elif kw in lower:
            return True
    return False


def has_korean_cultural_marker(text: str) -> bool:
    lower = text.lower()
    return any(kw in lower for kw in KOREAN_CULTURAL_KEYWORDS)


def is_mcq(text: str) -> bool:
    for pat in MCQ_PATTERNS:
        if re.search(pat, text, re.IGNORECASE | re.MULTILINE):
            return True
    return False


# ---------------------------------------------------------------------------
# Strategy selector — Hybrid-A
# ---------------------------------------------------------------------------
def select_strategy(text: str) -> RouteDecision:
    """
    Hybrid-A strategy decision:
      1) MCQ-style short answer → ensemble_v1
      2) Korean output + English/STEM reasoning needed → split_refine
      3) English output + Korean cultural context needed → split_refine_reverse
      4) Korean-dominant → route_awaxis
      5) English-dominant → route_darwin
      6) Mixed default → route_awaxis (Korean-first preference)
    """
    kr = korean_ratio(text)
    en = english_ratio(text)
    reasoning = has_reasoning_marker(text)
    cultural = has_korean_cultural_marker(text)
    mcq = is_mcq(text)

    decision = RouteDecision(
        strategy="route_awaxis",  # default
        reason="default",
        korean_ratio=round(kr, 3),
        english_ratio=round(en, 3),
        has_reasoning_marker=reasoning,
        has_korean_cultural_marker=cultural,
        is_mcq=mcq,
    )

    # 1. MCQ — always ensemble (10% case)
    if mcq and len(text) < 4000:
        decision.strategy = "ensemble_v1"
        decision.reason = "mcq_short_answer"
        return decision

    # 2. Korean output + reasoning required (15% case)
    if kr > 0.3 and reasoning:
        decision.strategy = "split_refine"
        decision.reason = "korean_output_with_english_reasoning"
        return decision

    # 3. English output + Korean cultural context (5% case)
    if en > 0.5 and kr < 0.05 and cultural:
        decision.strategy = "split_refine_reverse"
        decision.reason = "english_output_with_korean_context"
        return decision

    # 4. Korean-dominant (50% case)
    if kr >= 0.3:
        decision.strategy = "route_awaxis"
        decision.reason = "korean_dominant"
        return decision

    # 5. English-dominant (20% case)
    if en >= 0.5 and kr < 0.05:
        decision.strategy = "route_darwin"
        decision.reason = "english_dominant"
        return decision

    # 6. Mixed / ambiguous → AWAXIS (Korean-first default)
    decision.strategy = "route_awaxis"
    decision.reason = "mixed_fallback_korean"
    return decision


# ---------------------------------------------------------------------------
# Smoke test
# ---------------------------------------------------------------------------
if __name__ == "__main__":
    samples = [
        ("순수 한국어 채팅", "안녕하세요. 오늘 날씨가 어떤가요?"),
        ("순수 영어 코드", "def fib(n):\n    return n if n < 2 else fib(n-1) + fib(n-2)"),
        ("한국어 + 영어 reasoning", "Transformer attention의 작동 원리를 한국어로 설명해줘"),
        ("영어 + 한국 문화", "Explain the Korean Chuseok holiday in simple English."),
        ("MCQ", "Which is correct?\n(A) foo\n(B) bar\n(C) baz\n(D) qux"),
        ("한국어 MCQ", "정답은 무엇인가요? A. 1 B. 2 C. 3 D. 4"),
    ]
    for name, txt in samples:
        d = select_strategy(txt)
        print(f"[{name}] -> {d.strategy} ({d.reason}) kr={d.korean_ratio} en={d.english_ratio}")
