"""
browser_verify.py - 프론트엔드 변경에 대한 듀얼 MCP(Playwright + Chrome DevTools) 검증 verifier

MCP 도구를 직접 호출하지 않고, 팀장이 DIRECT-WORKFLOW에 따라 수행한
브라우저 검증의 증거(스크린샷, 보고서 기록)를 확인합니다.
"""

import os
import re
import glob

# task_id 유효성 검증 패턴 (경로 탈출 방어)
TASK_ID_PATTERN = re.compile(r'^task-\d[\w.\-]*$')

# 프론트엔드 파일/디렉토리 패턴
FRONTEND_EXT_PATTERNS = re.compile(
    r'\.(tsx|jsx|vue|svelte|html|css|scss)$', re.IGNORECASE
)
FRONTEND_DIR_PATTERNS = re.compile(
    r'(dashboard/|frontend/|static/|templates/)'
)

# 보고서에서 검증 수행 증거를 나타내는 키워드 패턴
CONSOLE_ERROR_PATTERN = re.compile(
    r'콘솔\s*에러\s*0\s*건|console\s*error[:\s]+0|no\s+console\s+error', re.IGNORECASE
)
LIGHTHOUSE_PATTERN = re.compile(
    r'lighthouse|성능\s*점수|performance\s*score|\blcp\b|\bfcp\b', re.IGNORECASE
)


def _parse_affected_files(content: str) -> list[str]:
    """task 파일의 ## affected_files 또는 ## 영향 파일 섹션 파싱."""
    lines = content.splitlines()
    in_section = False
    files = []
    section_headers = {"affected_files", "영향 파일", "affected files", "변경 파일"}

    for line in lines:
        stripped = line.strip()
        # 헤더 감지: ## 로 시작하는 경우
        if stripped.startswith("## "):
            header = stripped[3:].strip().lower()
            in_section = header in {h.lower() for h in section_headers}
            continue
        if in_section:
            if stripped.startswith("## "):
                break
            # 리스트 항목 (-  또는 * 또는 일반 텍스트)
            item = stripped.lstrip("-*• ").strip()
            if item:
                files.append(item)
    return files


def _is_frontend_change(files: list[str]) -> bool:
    """파일 목록에서 프론트엔드 변경 여부 판별."""
    for f in files:
        if FRONTEND_EXT_PATTERNS.search(f):
            return True
        if FRONTEND_DIR_PATTERNS.search(f):
            return True
    return False


def _find_screenshots(task_id: str, workspace_root: str) -> list[str]:
    """memory/screenshots/{task_id}*.png 스크린샷 파일 목록 반환."""
    screenshots_dir = os.path.join(workspace_root, "memory", "screenshots")
    if not os.path.isdir(screenshots_dir):
        return []
    pattern = os.path.join(screenshots_dir, f"{task_id}*.png")
    return glob.glob(pattern)


def _check_report(task_id: str, workspace_root: str) -> dict:
    """
    보고서 파일에서 콘솔 에러 / Lighthouse 기록 존재 여부 반환.
    Returns: {"has_console": bool, "has_lighthouse": bool, "exists": bool}
    """
    report_path = os.path.join(workspace_root, "memory", "reports", f"{task_id}.md")
    if not os.path.isfile(report_path):
        return {"has_console": False, "has_lighthouse": False, "exists": False}

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

    return {
        "has_console": bool(CONSOLE_ERROR_PATTERN.search(content)),
        "has_lighthouse": bool(LIGHTHOUSE_PATTERN.search(content)),
        "exists": True,
    }


def verify(task_id: str, workspace_root: str = "/home/jay/workspace") -> dict:
    """
    프론트엔드 변경 여부를 감지하고, 듀얼 MCP 브라우저 검증 증거를 확인합니다.

    Returns:
        {"status": "PASS"|"FAIL"|"SKIP"|"WARN", "details": [...]}

    판정 기준:
        SKIP : 프론트 변경 없음
        PASS : 프론트 변경 + 스크린샷 존재 + 보고서에 콘솔에러/Lighthouse 기록 존재
        WARN : 프론트 변경 + 스크린샷 존재 + Lighthouse 기록 없음
        FAIL : 프론트 변경인데 스크린샷 없음 (L1 스모크테스트 미수행)
    """
    # 경로 탈출 방어: task_id 형식 검증
    if not TASK_ID_PATTERN.match(task_id):
        return {"status": "FAIL", "details": [f"잘못된 task_id 형식: {task_id}"]}

    task_path = os.path.join(workspace_root, "memory", "tasks", f"{task_id}.md")

    if not os.path.isfile(task_path):
        return {"status": "SKIP", "details": [f"task 파일 없음: {task_path}"]}

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

    # 1. affected_files 파싱
    affected_files = _parse_affected_files(content)
    if not affected_files:
        return {"status": "SKIP", "details": ["affected_files 섹션 없음 또는 비어있음"]}

    # 2. 프론트엔드 변경 여부 판별
    if not _is_frontend_change(affected_files):
        return {
            "status": "SKIP",
            "details": [
                f"프론트엔드 변경 없음 (총 {len(affected_files)}개 파일 확인)",
            ],
        }

    details = [f"프론트엔드 변경 감지 — {len(affected_files)}개 파일"]

    # 3. 스크린샷 존재 확인
    screenshots = _find_screenshots(task_id, workspace_root)
    if not screenshots:
        details.append(
            f"FAIL: 스크린샷 없음 — memory/screenshots/{task_id}*.png 미발견"
        )
        details.append("Playwright MCP를 통한 L1 스모크테스트가 수행되지 않은 것으로 판정")
        return {"status": "FAIL", "details": details}

    details.append(f"스크린샷 확인: {len(screenshots)}개 ({', '.join(os.path.basename(s) for s in screenshots)})")

    # 4. 보고서 기록 확인
    report = _check_report(task_id, workspace_root)

    if not report["exists"]:
        details.append("WARN: 보고서 파일 없음 — Lighthouse/콘솔 에러 기록 미확인")
        return {"status": "WARN", "details": details}

    if report["has_console"]:
        details.append("콘솔 에러 기록 확인 (Chrome DevTools MCP 검증 증거)")
    else:
        details.append("WARN: 보고서에 콘솔 에러 기록 없음")

    if report["has_lighthouse"]:
        details.append("Lighthouse 점수 기록 확인")
    else:
        details.append("WARN: 보고서에 Lighthouse 기록 없음")

    # 5. 최종 판정: 콘솔 에러 기록 + Lighthouse 기록 모두 있어야 PASS
    if not report["has_console"] or not report["has_lighthouse"]:
        return {"status": "WARN", "details": details}

    return {"status": "PASS", "details": details}
