"""task-2503 회귀 테스트 파일 3 — dispatch.py main() hook 통합 검증.

회장 §6 회귀 테스트 (파일 3/3):
  - dispatch/__init__.py hook 코드 존재 검증 (grep 기반)
  - --override-merge-topology-gate argparse 등록 검증
  - BLOCK 시 sys.exit(1) 호출 검증
  - run_gate 호출 가능성 검증
  - AUDIT_LOG_PATH monkeypatch로 실제 audit 파일 오염 방지
"""
import re
import sys
from pathlib import Path

import pytest

# workspace root를 sys.path에 추가
WORKSPACE = Path(__file__).resolve().parent.parent.parent
if str(WORKSPACE) not in sys.path:
    sys.path.insert(0, str(WORKSPACE))

DISPATCH_FILE = WORKSPACE / "dispatch" / "__init__.py"


# ═══════════════════════════════════════════════════════════════════════════
# TC-1: dispatch/__init__.py import 에러 없음 + run_gate 호출 가능
# ═══════════════════════════════════════════════════════════════════════════
def test_dispatch_imports_merge_topology_gate():
    """dispatch/__init__.py를 import해도 에러 없음 + from utils.merge_topology_gate import run_gate 호출 가능."""
    # dispatch 모듈 import 가능 여부 검증
    try:
        import dispatch as _dispatch_mod  # type: ignore[import]
        assert _dispatch_mod is not None
    except Exception as e:
        pytest.fail(f"dispatch module import failed: {e}")

    # run_gate 직접 import 가능 여부 검증
    try:
        from utils.merge_topology_gate import run_gate  # type: ignore[import]
        assert callable(run_gate), "run_gate must be callable"
    except ImportError as e:
        pytest.fail(f"run_gate import failed: {e}")


# ═══════════════════════════════════════════════════════════════════════════
# TC-2: dispatch/__init__.py에 --override-merge-topology-gate argparse 등록
# ═══════════════════════════════════════════════════════════════════════════
def test_dispatch_argparse_has_override_flag():
    """dispatch/__init__.py에 --override-merge-topology-gate 인자와 dest 등록 확인 (grep)."""
    assert DISPATCH_FILE.exists(), f"dispatch/__init__.py not found: {DISPATCH_FILE}"
    content = DISPATCH_FILE.read_text(encoding="utf-8")

    assert "--override-merge-topology-gate" in content, (
        "--override-merge-topology-gate flag must be registered in dispatch argparse"
    )
    assert 'dest="override_merge_topology_gate"' in content, (
        'dest="override_merge_topology_gate" must be set in argparse add_argument'
    )


# ═══════════════════════════════════════════════════════════════════════════
# TC-3: hook 블록에 sys.exit(1) 존재 (BLOCK 시 dispatch 거부)
# ═══════════════════════════════════════════════════════════════════════════
def test_dispatch_main_block_decision_exits_with_error():
    """dispatch/__init__.py의 merge-topology-gate hook 블록에 sys.exit(1) 존재 검증."""
    assert DISPATCH_FILE.exists(), f"dispatch/__init__.py not found: {DISPATCH_FILE}"
    content = DISPATCH_FILE.read_text(encoding="utf-8")

    # hook 블록 ([merge-topology-gate] 주석 ~ sys.exit(1)) 존재 검증
    hook_match = re.search(
        r"\[merge-topology-gate\].*?sys\.exit\(1\)",
        content,
        re.DOTALL,
    )
    assert hook_match is not None, (
        "dispatch/__init__.py hook block must call sys.exit(1) on BLOCK decision"
    )

    # "Merge Topology Gate 차단" 메시지도 존재해야 함
    assert "Merge Topology Gate 차단" in content, (
        '"Merge Topology Gate 차단" message must exist in hook block'
    )


# ═══════════════════════════════════════════════════════════════════════════
# TC-4: dispatch/__init__.py에 run_gate import 문 존재 (hook 등록 확인)
# ═══════════════════════════════════════════════════════════════════════════
def test_dispatch_main_allow_decision_proceeds():
    """dispatch/__init__.py에 from utils.merge_topology_gate import run_gate 존재 (hook 등록 확인)."""
    assert DISPATCH_FILE.exists(), f"dispatch/__init__.py not found: {DISPATCH_FILE}"
    content = DISPATCH_FILE.read_text(encoding="utf-8")

    assert "from utils.merge_topology_gate import run_gate" in content, (
        "dispatch/__init__.py must import run_gate from utils.merge_topology_gate"
    )


# ═══════════════════════════════════════════════════════════════════════════
# 추가: run_gate — empty task_desc → BLOCK + allowed=False (단위 검증)
# ═══════════════════════════════════════════════════════════════════════════
def test_run_gate_callable_with_minimal_args(tmp_path, monkeypatch):
    """run_gate — empty task_desc → metadata 누락 → BLOCK + allowed=False."""
    from utils.merge_topology_gate import run_gate  # type: ignore[import]

    # AUDIT_LOG_PATH monkeypatch (실제 audit 파일 오염 방지)
    audit_file = tmp_path / "merge-topology-gate.jsonl"
    monkeypatch.setattr(
        "utils.merge_topology_gate.AUDIT_LOG_PATH",
        audit_file,
    )

    decision, allowed = run_gate(task_id="test-empty", task_desc="")
    assert decision.decision == "BLOCK", (
        f"empty task_desc must result in BLOCK, got {decision.decision}"
    )
    assert allowed is False, f"expected allowed=False, got {allowed}"
