"""
l1_smoketest_check.py - 보고서 파일의 L1 스모크테스트 섹션 검증 verifier
보고서의 ## L1 스모크테스트 / ## 스모크테스트 결과 섹션 유무 및 결과 키워드 확인.
섹션 없으면 FAIL, 파일 없으면 SKIP.
"""

import os
import re


BLOCK_PATTERNS = [
    r"UI 직접 확인 불가",
    r"서버 기동 불가",
    r"환경 제약으로 확인 불가",
    r"해당없음.*스모크",
    r"N/A.*L1",
]

FRONTEND_KEYWORDS = ["UI", "컴포넌트", "화면", "페이지", "프론트", "frontend", "component"]


def verify(task_id: str, workspace_root: str = "/home/jay/workspace") -> dict:
    """
    보고서 파일의 L1 스모크테스트 섹션을 파싱하여 결과를 검증.

    Returns:
        {"status": "PASS"|"FAIL"|"SKIP", "details": [...]}
    """
    report_path = os.path.join(workspace_root, "memory", "reports", f"{task_id}.md")

    if not os.path.isfile(report_path):
        return {"status": "SKIP", "details": ["보고서 파일 없음"]}

    with open(report_path, "r", encoding="utf-8") as f:
        content = f.read()

    # BLOCK 패턴 체크 — 매칭 시 즉시 FAIL
    for pattern in BLOCK_PATTERNS:
        if re.search(pattern, content):
            return {"status": "FAIL", "details": [f"BLOCK 패턴 매칭: {pattern}"]}

    # ##/### 레벨 헤더에서 "L1 스모크테스트" 또는 "스모크테스트 결과" 섹션 탐색
    section_lines = _find_smoketest_section(content)

    if section_lines is None:
        return {"status": "FAIL", "details": ["L1 스모크테스트 섹션 없음"]}

    # task 파일 읽어 is_frontend 판별
    task_path = os.path.join(workspace_root, "memory", "tasks", f"{task_id}.md")
    is_frontend = False
    try:
        with open(task_path, "r", encoding="utf-8") as f:
            task_content = f.read()
        for keyword in FRONTEND_KEYWORDS:
            if keyword in task_content:
                is_frontend = True
                break
    except Exception:
        is_frontend = False

    # "해당없음" 이 3줄 이상인 경우 처리
    naexclusion_count = sum(1 for line in section_lines if "해당없음" in line)
    if naexclusion_count >= 3:
        if not is_frontend:
            # 백엔드/유틸 작업 — 기존 동작 유지
            return {"status": "PASS", "details": ["CLI/스크립트 작업 — 해당없음 3줄 이상"]}
        # 프론트 작업이면 면제 무효화, 스크린샷 필수로 아래 로직 계속 진행

    # 결과 키워드 확인
    result_keywords = ["성공", "실패", "확인", "PASS", "OK"]
    section_text = "\n".join(section_lines)
    has_keyword = any(keyword in section_text for keyword in result_keywords)

    # 증거 필수 체크
    has_screenshot = bool(re.search(r'(screenshot|스크린샷|\.png|\.jpg)', section_text, re.I))
    has_curl = bool(re.search(r'(curl.*200|HTTP/.*200|응답 코드.*200|200\s*OK)', section_text, re.I))
    has_test_output = bool(re.search(r'(pytest.*pass|tests?\s+passed|\d+\s+passed)', section_text, re.I))

    has_evidence = has_screenshot or has_curl or has_test_output

    if not has_evidence:
        return {"status": "FAIL", "details": ["L1 증거 부족: 스크린샷/curl/테스트 결과 중 하나 필수"]}

    if has_keyword or has_evidence:
        return {"status": "PASS", "details": ["L1 결과 확인됨"]}

    return {"status": "FAIL", "details": ["L1 섹션 있으나 결과 키워드 미발견"]}


def _find_smoketest_section(content: str) -> list[str] | None:
    """
    ##/### 레벨 헤더에서 'L1 스모크테스트' 또는 '스모크테스트 결과' 섹션을 찾아
    다음 동등 이상 레벨 헤더 전까지의 줄 목록을 반환.
    섹션이 없으면 None 반환.
    """
    header_pattern = re.compile(r"^(#{2,3})\s+(.+)$")
    smoketest_keywords = ["L1 스모크테스트", "스모크테스트 결과"]

    lines = content.splitlines()
    in_section = False
    section_header_level = 0
    result = []

    for line in lines:
        match = header_pattern.match(line)
        if match:
            level = len(match.group(1))
            header_text = match.group(2).strip()

            if in_section:
                # 동등 이상 레벨의 헤더 발견 시 섹션 종료
                if level <= section_header_level:
                    break
            else:
                # 스모크테스트 관련 헤더인지 확인
                for keyword in smoketest_keywords:
                    if keyword in header_text:
                        in_section = True
                        section_header_level = level
                        break
            continue

        if in_section:
            result.append(line)

    if not in_section:
        return None

    return result
