#!/usr/bin/env python3
"""
test_l1_smoketest_check.py — l1_smoketest_check.py의 verify 함수 단위 테스트.

10개 시나리오:
1. 보고서 파일 없음 → SKIP
2. 보고서에 L1 섹션 없음 → FAIL
3. BLOCK 패턴 매칭 → FAIL
4. 백엔드 작업 + 해당없음 3줄 → PASS (EXEMPT)
5. 프론트 작업 + 해당없음 3줄 → FAIL (EXEMPT 무효화)
6. 증거 누락 → FAIL
7. 정상 스크린샷 증거 → PASS
8. 정상 curl 증거 → PASS
9. 정상 pytest 증거 → PASS
10. BLOCK 패턴 "N/A.*L1" 매칭 → FAIL
"""

import importlib.util
from pathlib import Path

# l1_smoketest_check.py를 직접 로드 (패키지 __init__ 부작용 회피)
_MODULE_PATH = Path(__file__).parent.parent / "l1_smoketest_check.py"
_spec = importlib.util.spec_from_file_location("l1_smoketest_check", _MODULE_PATH)
assert _spec is not None and _spec.loader is not None
_module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module)  # type: ignore[union-attr]

verify = _module.verify

TASK_ID = "task-test-9999"


def _write_report(tmp_path: Path, content: str) -> None:
    """tmp_path/memory/reports/{TASK_ID}.md 에 content를 기록."""
    report_dir = tmp_path / "memory" / "reports"
    report_dir.mkdir(parents=True, exist_ok=True)
    (report_dir / f"{TASK_ID}.md").write_text(content, encoding="utf-8")


def _write_task(tmp_path: Path, content: str) -> None:
    """tmp_path/memory/tasks/{TASK_ID}.md 에 content를 기록."""
    task_dir = tmp_path / "memory" / "tasks"
    task_dir.mkdir(parents=True, exist_ok=True)
    (task_dir / f"{TASK_ID}.md").write_text(content, encoding="utf-8")


# ---------------------------------------------------------------------------
# 시나리오 1: 보고서 파일 없음 → SKIP
# ---------------------------------------------------------------------------


def test_no_report_file_returns_skip(tmp_path):
    """보고서 파일 자체가 없으면 SKIP을 반환해야 한다."""
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "SKIP"
    assert result["details"]  # 최소 1개 이상의 안내 메시지


# ---------------------------------------------------------------------------
# 시나리오 2: 보고서에 L1 섹션 없음 → FAIL
# ---------------------------------------------------------------------------


def test_no_l1_section_returns_fail(tmp_path):
    """보고서 파일은 있으나 L1 스모크테스트 섹션이 없으면 FAIL을 반환해야 한다."""
    content = """\
## 작업 개요

이 작업은 간단한 리팩토링입니다.

## 변경 내역

- 일부 코드 정리
"""
    _write_report(tmp_path, content)
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "FAIL"


# ---------------------------------------------------------------------------
# 시나리오 3: BLOCK 패턴 매칭 → FAIL
# ---------------------------------------------------------------------------


def test_block_pattern_ui_direct_returns_fail(tmp_path):
    """보고서에 'UI 직접 확인 불가' 패턴이 있으면 FAIL이며 details에 'BLOCK 패턴'이 포함된다."""
    content = """\
## L1 스모크테스트 결과

- UI 직접 확인 불가 (원격 환경 제약)
- 스크린샷: 해당없음
"""
    _write_report(tmp_path, content)
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "FAIL"
    assert any("BLOCK 패턴" in d for d in result["details"])


# ---------------------------------------------------------------------------
# 시나리오 4: 백엔드 작업 + 해당없음 3줄 → PASS (EXEMPT)
# ---------------------------------------------------------------------------


def test_backend_task_three_naexclusions_returns_pass(tmp_path):
    """
    task 파일에 UI/프론트 키워드 없고 보고서에 해당없음 3줄 이상이면 PASS (면제).
    """
    _write_task(tmp_path, "배치 스크립트 로그 포맷 개선 작업입니다.")
    content = """\
## 작업 개요

배치 스크립트 수정 작업입니다.

## L1 스모크테스트 결과

- 서버 재시작: 해당없음 (배치 스크립트, 서버 코드 아님)
- API 응답 확인: 해당없음
- 스크린샷: 해당없음
"""
    _write_report(tmp_path, content)
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "PASS"


# ---------------------------------------------------------------------------
# 시나리오 5: 프론트 작업 + 해당없음 3줄 → FAIL (EXEMPT 무효화)
# ---------------------------------------------------------------------------


def test_frontend_task_three_naexclusions_returns_fail(tmp_path):
    """
    task 파일에 'UI 컴포넌트' 키워드가 있고 보고서에 해당없음 3줄 + 증거 없으면 FAIL.
    (프론트 작업이므로 면제 무효화)
    """
    _write_task(tmp_path, "UI 컴포넌트 수정 작업입니다. 버튼 스타일 변경.")
    content = """\
## L1 스모크테스트 결과

- 버튼 렌더링: 해당없음
- 화면 전환: 해당없음
- 레이아웃 확인: 해당없음
"""
    _write_report(tmp_path, content)
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "FAIL"


# ---------------------------------------------------------------------------
# 시나리오 6: 증거 누락 → FAIL
# ---------------------------------------------------------------------------


def test_keyword_without_evidence_returns_fail(tmp_path):
    """L1 섹션에 '성공' 키워드가 있어도 스크린샷/curl/테스트 증거가 없으면 FAIL."""
    content = """\
## L1 스모크테스트 결과

- 서버 재시작 성공
- 동작 확인 완료
"""
    _write_report(tmp_path, content)
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "FAIL"
    assert any("증거 부족" in d for d in result["details"])


# ---------------------------------------------------------------------------
# 시나리오 7: 정상 스크린샷 증거 → PASS
# ---------------------------------------------------------------------------


def test_screenshot_evidence_returns_pass(tmp_path):
    """L1 섹션에 '성공' 키워드 + 스크린샷 경로(.png)가 있으면 PASS."""
    content = """\
## L1 스모크테스트 결과

- 화면 동작 성공
- 스크린샷: /path/to/screenshot.png
"""
    _write_report(tmp_path, content)
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "PASS"


# ---------------------------------------------------------------------------
# 시나리오 8: 정상 curl 증거 → PASS
# ---------------------------------------------------------------------------


def test_curl_evidence_returns_pass(tmp_path):
    """L1 섹션에 '확인' 키워드 + 'curl 200 OK' 증거가 있으면 PASS."""
    content = """\
## L1 스모크테스트 결과

- API 응답 확인 완료
- curl 200 OK 응답 수신
"""
    _write_report(tmp_path, content)
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "PASS"


# ---------------------------------------------------------------------------
# 시나리오 9: 정상 pytest 증거 → PASS
# ---------------------------------------------------------------------------


def test_pytest_evidence_returns_pass(tmp_path):
    """L1 섹션에 '확인' 키워드 + 'pytest 33 passed' 증거가 있으면 PASS."""
    content = """\
## L1 스모크테스트 결과

- 테스트 실행 결과 확인
- pytest 33 passed, 0 failed
"""
    _write_report(tmp_path, content)
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "PASS"


# ---------------------------------------------------------------------------
# 시나리오 10: BLOCK 패턴 "N/A.*L1" 매칭 → FAIL
# ---------------------------------------------------------------------------


def test_block_pattern_na_l1_returns_fail(tmp_path):
    """보고서에 'N/A - L1 스킵' 패턴이 있으면 FAIL이며 details에 'BLOCK 패턴'이 포함된다."""
    content = """\
## 작업 개요

간단한 설정 파일 수정입니다.

## L1 스모크테스트 결과

- N/A - L1 스킵 (설정 파일 변경만)
"""
    _write_report(tmp_path, content)
    result = verify(TASK_ID, workspace_root=str(tmp_path))
    assert result["status"] == "FAIL"
    assert any("BLOCK 패턴" in d for d in result["details"])
