"""
three_docs_check.py - 3문서 검증 verifier

Lv.3+ 작업의 plan.md, context-notes.md, checklist.md 존재 및 내용 검증.
- YAML frontmatter 필수 필드 확인
- plan.md status 업데이트 여부
- 플레이스홀더 미치환 탐지
- checklist 완료율 50% 미만 시 WARN
"""

import os
import re

import yaml

REQUIRED_DOCS = ["plan.md", "context-notes.md", "checklist.md"]
REQUIRED_YAML_FIELDS = ["task_id", "type", "scope", "status"]

# 명백히 플레이스홀더인 패턴 (짧은 링크/코드가 아닌 한글/영어 설명 형태)
_PLACEHOLDER_RE = re.compile(r"\[[가-힣a-zA-Z\s]{2,30}\]")


def _parse_frontmatter(content: str) -> tuple[dict | None, str]:
    """
    YAML frontmatter(--- ... ---) 파싱.

    Returns:
        (frontmatter_dict, body) — 파싱 실패 시 (None, content)
    """
    if not content.startswith("---"):
        return None, content

    end = content.find("\n---", 3)
    if end == -1:
        return None, content

    yaml_block = content[3:end].strip()
    body = content[end + 4:].strip()

    try:
        data = yaml.safe_load(yaml_block)
        if not isinstance(data, dict):
            return None, content
        return data, body
    except yaml.YAMLError:
        return None, content


def _has_placeholder(body: str) -> bool:
    """본문에 미치환 플레이스홀더가 있는지 확인."""
    return bool(_PLACEHOLDER_RE.search(body))


def _checklist_completion(body: str) -> tuple[int, int]:
    """
    checklist.md 본문에서 완료/전체 항목 수 반환.

    Returns:
        (completed, total)
    """
    checked = len(re.findall(r"- \[x\]", body, re.IGNORECASE))
    unchecked = len(re.findall(r"- \[ \]", body))
    return checked, checked + unchecked


def verify(task_id: str, report_path: str = "", workspace: str = "/home/jay/workspace") -> dict:
    _ = report_path  # verifier 인터페이스 호환용
    """
    3문서 검증기. Lv.3+ 작업의 plan.md, context-notes.md, checklist.md 검증.

    Returns:
        {"name": "three_docs_check", "status": "PASS"|"FAIL"|"WARN"|"SKIP", "message": "...", "details": {...}}
    """
    docs_dir = os.path.join(workspace, "memory", "plans", "tasks", task_id)

    # ── SKIP 조건: 디렉토리 없음 ──
    if not os.path.isdir(docs_dir):
        return {
            "name": "three_docs_check",
            "status": "SKIP",
            "message": f"3문서 디렉토리 없음 — Lv.2 이하 작업으로 간주: {docs_dir}",
            "details": {
                "directory": docs_dir,
                "checks": [],
            },
        }

    checks = []
    warns: list[str] = []
    fails: list[str] = []

    # ── 1. 파일 존재 검증 ──
    missing_files: list[str] = []
    for fname in REQUIRED_DOCS:
        fpath = os.path.join(docs_dir, fname)
        if os.path.isfile(fpath):
            checks.append({"file": fname, "exists": True})
        else:
            missing_files.append(fname)
            checks.append({"file": fname, "exists": False})

    if missing_files:
        return {
            "name": "three_docs_check",
            "status": "FAIL",
            "message": f"필수 파일 누락: {', '.join(missing_files)}",
            "details": {
                "directory": docs_dir,
                "checks": checks,
                "missing_files": missing_files,
            },
        }

    # ── 2~4. 각 파일 내용 검증 ──
    file_results: list[dict] = []

    for fname in REQUIRED_DOCS:
        fpath = os.path.join(docs_dir, fname)
        result: dict = {"file": fname, "path": fpath}

        try:
            with open(fpath, encoding="utf-8") as f:
                content = f.read()
        except OSError as e:
            result["error"] = f"읽기 오류: {e}"
            fails.append(f"{fname}: 읽기 오류 — {e}")
            file_results.append(result)
            continue

        # YAML frontmatter 파싱
        fm, body = _parse_frontmatter(content)

        if fm is None:
            result["yaml"] = "FAIL: frontmatter 파싱 실패"
            fails.append(f"{fname}: YAML frontmatter 파싱 실패")
            file_results.append(result)
            continue

        result["yaml"] = "OK"

        # 필수 필드 확인
        missing_fields = [f for f in REQUIRED_YAML_FIELDS if f not in fm]
        if missing_fields:
            result["missing_fields"] = missing_fields
            fails.append(f"{fname}: 필수 YAML 필드 누락 {missing_fields}")
        else:
            result["missing_fields"] = []

        # plan.md status 검증
        if fname == "plan.md":
            plan_status = fm.get("status", "")
            result["plan_status"] = plan_status
            if plan_status == "draft":
                warns.append(f"plan.md status=draft (미업데이트)")
                result["status_warn"] = True
            else:
                result["status_warn"] = False

        # 플레이스홀더 탐지
        if _has_placeholder(body):
            warns.append(f"{fname}: 플레이스홀더 미치환 탐지")
            result["placeholder"] = True
        else:
            result["placeholder"] = False

        # checklist 완료율
        if fname == "checklist.md":
            completed, total = _checklist_completion(body)
            result["checklist_completed"] = completed
            result["checklist_total"] = total
            if total > 0:
                ratio = completed / total
                result["checklist_ratio"] = round(ratio, 2)
                if ratio < 0.5:
                    warns.append(f"checklist.md 완료율 {completed}/{total} ({ratio:.0%}) — 50% 미만")
            else:
                result["checklist_ratio"] = None

        file_results.append(result)

    # ── 최종 판정 ──
    all_checks = checks + [{"file_results": file_results}]

    if fails:
        status = "FAIL"
        message = f"검증 실패: {'; '.join(fails)}"
    elif warns:
        status = "WARN"
        message = f"경고: {'; '.join(warns)}"
    else:
        status = "PASS"
        message = "3문서 검증 통과"

    return {
        "name": "three_docs_check",
        "status": status,
        "message": message,
        "details": {
            "directory": docs_dir,
            "checks": all_checks,
            "file_results": file_results,
            "fails": fails,
            "warns": warns,
        },
    }


if __name__ == "__main__":
    import json
    import sys

    tid = sys.argv[1] if len(sys.argv) > 1 else ""
    ws = sys.argv[2] if len(sys.argv) > 2 else "/home/jay/workspace"

    if not tid:
        print("Usage: three_docs_check.py <task_id> [workspace]", file=sys.stderr)
        sys.exit(1)

    result = verify(task_id=tid, workspace=ws)
    print(json.dumps(result, ensure_ascii=False, indent=2))
    sys.exit(0 if result["status"] in ("PASS", "SKIP") else 1)
