"""위험 명령어 승인 모듈.

명령어에서 위험 패턴을 탐지하고 위험 레벨을 판단합니다.
LLM 호출 없이 정규식 기반으로만 동작합니다.
Hermes Agent의 approval.py 패턴 목록을 참고하여 dev2-team 시스템에 맞게 재설계.

Usage:
    from utils.approval import check_command
    result = check_command("rm -rf /")
    if not result.is_safe:
        print(result.risk_level, result.matched_patterns)
"""

import re
from dataclasses import dataclass, field

# ---------------------------------------------------------------------------
# 위험 패턴 정의
# (regex, description, risk_level)
# risk_level: "critical" | "high" | "medium" | "low"
# ---------------------------------------------------------------------------
_PATTERNS: list[tuple[str, str, str]] = [
    # ── CRITICAL ────────────────────────────────────────────────────────────
    # rm -rf / (루트 전체 삭제)
    (
        r"\brm\s+(-[^\s]*\s+)*-[^\s]*r[^\s]*\s+/\s*$",
        "rm -rf /",
        "critical",
    ),
    (
        r"\brm\s+-rf\s+/",
        "rm -rf /",
        "critical",
    ),
    # DROP TABLE / DROP DATABASE
    (
        r"\bDROP\s+(TABLE|DATABASE)\b",
        "DROP TABLE/DATABASE",
        "critical",
    ),
    # Fork bomb
    (
        r":\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:",
        "fork bomb",
        "critical",
    ),
    # dd if=/dev/zero (디스크 초기화)
    (
        r"\bdd\b[^\n]*\bif=/dev/zero\b",
        "dd if=/dev/zero",
        "critical",
    ),
    # ── HIGH ────────────────────────────────────────────────────────────────
    # curl|bash / wget|bash (원격 실행)
    (
        r"\b(curl|wget)\b[^\n]*\|\s*(ba)?sh\b",
        "curl|bash remote execution",
        "high",
    ),
    # eval
    (
        r"\beval\b",
        "eval execution",
        "high",
    ),
    # rm -rf (루트가 아닌 재귀 삭제)
    (
        r"\brm\s+(-[^\s]*\s+)*-[^\s]*r",
        "rm -rf recursive delete",
        "high",
    ),
    # git push --force
    (
        r"\bgit\s+push\b[^\n]*--force\b",
        "git push --force",
        "high",
    ),
    # chmod 777
    (
        r"\bchmod\b[^\n]*\b777\b",
        "chmod 777",
        "high",
    ),
    # ── MEDIUM ──────────────────────────────────────────────────────────────
    # sudo
    (
        r"\bsudo\b",
        "sudo",
        "medium",
    ),
    # pip install
    (
        r"\bpip\s+install\b",
        "pip install",
        "medium",
    ),
    # npm install -g
    (
        r"\bnpm\s+install\b[^\n]*\s-g\b|\bnpm\s+install\s+-g\b",
        "npm install -g",
        "medium",
    ),
    # docker run --privileged
    (
        r"\bdocker\s+run\b[^\n]*--privileged\b",
        "docker run --privileged",
        "medium",
    ),
    # ── LOW ─────────────────────────────────────────────────────────────────
    # git reset
    (
        r"\bgit\s+reset\b",
        "git reset",
        "low",
    ),
    # git checkout .
    (
        r"\bgit\s+checkout\s+\.",
        "git checkout .",
        "low",
    ),
]

# 위험도 우선순위 (높을수록 심각)
_LEVEL_PRIORITY: dict[str, int] = {
    "safe": 0,
    "low": 1,
    "medium": 2,
    "high": 3,
    "critical": 4,
}

_RECOMMENDATIONS: dict[str, str] = {
    "safe": "명령어를 실행해도 안전합니다.",
    "low": "낮은 위험도입니다. 의도한 동작인지 확인 후 실행하세요.",
    "medium": "중간 위험도입니다. 영향 범위를 검토하고 신중하게 실행하세요.",
    "high": "높은 위험도입니다. 반드시 내용을 검토하고 책임자 승인 후 실행하세요.",
    "critical": "치명적 위험도입니다. 실행 시 복구 불가능한 손실이 발생할 수 있습니다. 실행을 강력히 거부합니다.",
}


@dataclass
class ApprovalResult:
    """명령어 승인 판단 결과."""

    is_safe: bool
    risk_level: str  # "safe" | "low" | "medium" | "high" | "critical"
    matched_patterns: list[str] = field(default_factory=list)
    recommendation: str = ""


def check_command(command: str) -> ApprovalResult:
    """명령어에서 위험 패턴을 탐지하고 위험 레벨을 반환합니다.

    Args:
        command: 검사할 셸 명령어 문자열.

    Returns:
        ApprovalResult: 위험 레벨, 매칭된 패턴 목록, 권고사항 포함.
    """
    matched: list[str] = []
    highest_level = "safe"

    for pattern, description, level in _PATTERNS:
        if re.search(pattern, command, re.IGNORECASE | re.DOTALL):
            # 같은 description 중복 방지
            if description not in matched:
                matched.append(description)
            if _LEVEL_PRIORITY[level] > _LEVEL_PRIORITY[highest_level]:
                highest_level = level

    is_safe = highest_level == "safe"
    return ApprovalResult(
        is_safe=is_safe,
        risk_level=highest_level,
        matched_patterns=matched,
        recommendation=_RECOMMENDATIONS[highest_level],
    )
