"""
GUARDiA NLU Engine — 순수 규칙 기반 자연어 이해 (외부 API 없음).

처리 흐름:
  1. 정규식 패턴 매칭으로 인텐트(의도) 분류
  2. 키워드/패턴으로 엔티티 추출
  3. (sr_id, engineer, status, sr_type, inst_code, priority, keyword)
"""
import re
from dataclasses import dataclass, field
from typing import Optional


# ── 인텐트 정의 ───────────────────────────────────────────────────────────────

INTENT_PATTERNS: list[tuple[str, list[str]]] = [
    # 우선순위 높은 인텐트부터

    # SR 작업 시뮬레이션 실행
    ("SIMULATE", [
        r"(시뮬레이션|simulate|작업\s*실행|자동\s*실행|AI\s*실행)",
        r"(실행|run).*(SR|작업)",
    ]),

    # 담당자 배정·변경
    ("ASSIGN_ENGINEER", [
        r"담당자.*(변경|바꿔|배정|교체|지정)",
        r"(배정|assign).*(engineer|엔지니어)",
        r"engineer\d+.*(맡겨|담당|배정|지정)",
        r"(자동\s*배정|auto\s*assign)",
    ]),

    # 승인
    ("APPROVE_SR", [
        r"(승인|approve)\s*(해줘|처리|완료|부탁)",
        r"결재\s*(해줘|처리)",
    ]),

    # 반려
    ("REJECT_SR", [
        r"(반려|거절|reject)\s*(해줘|처리|할게)",
    ]),

    # KB 검색
    ("SEARCH_KB", [
        r"(KB|기술\s*문서|지식|매뉴얼).*(검색|찾아|조회)",
        r"(검색|찾아줘|알려줘).*(오류|error|fault|장애|문제)",
        r"(해결\s*방법|원인|솔루션).*(알려줘|찾아줘)",
        r"(oom|outofmemory|connection\s*pool|ssl|nginx|502|undo|gc\s*overhead|디스크)",
    ]),

    # 워크로드 조회
    ("QUERY_WORKLOAD", [
        r"(워크로드|workload|작업\s*현황|담당\s*현황)",
        r"engineer.*(몇\s*건|현황|상황|바빠)",
        r"(엔지니어|engineer).*(상황|현황|보여줘)",
    ]),

    # SR 상세 조회
    ("QUERY_SR_DETAIL", [
        r"SR-\d{8}-[A-Z0-9]{6}.*(상태|정보|내용|어떻게|확인)",
        r"(상태|정보|현황).*(알려줘|보여줘|확인).*(SR|서비스)",
    ]),

    # SR 목록 조회
    ("QUERY_SR_LIST", [
        r"(목록|리스트|list|조회|보여줘).*(SR|서비스|요청)",
        r"(SR|서비스\s*요청).*(목록|있어|있나|몇\s*건|현황|리스트)",
        r"(승인\s*대기|진행\s*중|완료|긴급|접수).*(SR|서비스|있어|있나|보여)",
        r"(어떤|무슨)\s*SR",
    ]),

    # 통계/요약
    ("QUERY_STATS", [
        r"(통계|요약|summary|stats|현황\s*요약|전체\s*현황)",
        r"(총|전체).*(SR|건수|몇\s*건)",
        r"(오늘|이번\s*주).*(SR|처리|완료)",
    ]),
]


# ── 엔티티 추출 ───────────────────────────────────────────────────────────────

_SR_ID_RE       = re.compile(r'SR-\d{8}-[A-Z0-9]{6}', re.IGNORECASE)
_ENG_USER_RE    = re.compile(r'engineer\d+', re.IGNORECASE)
_PRIORITY_MAP   = {"긴급": "CRITICAL", "높음": "HIGH", "보통": "MEDIUM", "낮음": "LOW",
                   "critical": "CRITICAL", "high": "HIGH", "medium": "MEDIUM", "low": "LOW"}
_STATUS_MAP     = {
    "승인": "APPROVED", "반려": "REJECTED", "완료": "COMPLETED",
    "진행": "IN_PROGRESS", "접수": "RECEIVED", "대기": "PENDING_APPROVAL",
}
_TYPE_MAP       = {
    "배포": "DEPLOY", "deploy": "DEPLOY",
    "재기동": "RESTART", "restart": "RESTART",
    "로그": "LOG", "log": "LOG",
    "문의": "INQUIRY", "inquiry": "INQUIRY",
}
_INST_CODES     = ["MOF", "MOIS", "MSS"]
_ENG_ALIAS      = {"김엔지니어": "engineer1", "이엔지니어": "engineer2"}


@dataclass
class ParseResult:
    intent:    str              = "UNKNOWN"
    sr_id:     Optional[str]   = None
    engineer:  Optional[str]   = None
    status:    Optional[str]   = None
    sr_type:   Optional[str]   = None
    inst_code: Optional[str]   = None
    priority:  Optional[str]   = None
    keyword:   Optional[str]   = None
    raw_text:  str              = ""


def parse(text: str) -> ParseResult:
    """자연어 텍스트를 분석해 인텐트 + 엔티티를 반환."""
    r     = ParseResult(raw_text=text)
    lower = text.lower()

    # ── 인텐트 분류 ──────────────────────────────────────
    for intent_name, patterns in INTENT_PATTERNS:
        for pat in patterns:
            if re.search(pat, text, re.IGNORECASE):
                r.intent = intent_name
                break
        if r.intent != "UNKNOWN":
            break

    # ── 엔티티 추출 ──────────────────────────────────────
    # SR ID
    m = _SR_ID_RE.search(text)
    if m:
        r.sr_id = m.group().upper()

    # 엔지니어 (username 또는 한글 별칭)
    m = _ENG_USER_RE.search(text)
    if m:
        r.engineer = m.group().lower()
    else:
        for alias, uname in _ENG_ALIAS.items():
            if alias in text:
                r.engineer = uname
                break

    # 상태
    for k, v in _STATUS_MAP.items():
        if k in lower:
            r.status = v
            break

    # SR 유형
    for k, v in _TYPE_MAP.items():
        if k in lower:
            r.sr_type = v
            break

    # 기관 코드
    for inst in _INST_CODES:
        if inst in text.upper():
            r.inst_code = inst
            break

    # 우선순위
    for k, v in _PRIORITY_MAP.items():
        if k in lower:
            r.priority = v
            break

    # 키워드 (KB 검색용) — 따옴표 안 또는 '검색:' 뒤
    qm = re.search(r'["\'](.+?)["\']', text)
    if qm:
        r.keyword = qm.group(1)
    else:
        # fallback: 큰 단어 추출
        kb_kw = re.search(
            r'(oom|outofmemory|connection\s*pool|ssl|nginx|502|undo|gc overhead'
            r'|디스크|메모리|커넥션|인증서|tomcat|oracle|ora-\d+)',
            text, re.IGNORECASE
        )
        if kb_kw:
            r.keyword = kb_kw.group(1)

    return r
