"""skill-quality-check.py 단위 테스트.

테스트 대상:
- parse_frontmatter(text) — YAML frontmatter 파싱
- check_skill(skill_name, skill_dir, registry, eval_axes) — 단일 스킬 검증
- main() --summary 모드 실행 (subprocess)
"""

from __future__ import annotations

import subprocess
import sys
from pathlib import Path

# scripts/ 디렉토리를 import 경로에 추가
_SCRIPTS_DIR = Path("/home/jay/workspace/scripts")
if str(_SCRIPTS_DIR) not in sys.path:
    sys.path.insert(0, str(_SCRIPTS_DIR))

# 모듈 이름에 하이픈이 포함되어 있으므로 importlib 사용
import importlib.util as _ilu

_spec = _ilu.spec_from_file_location(
    "skill_quality_check",
    _SCRIPTS_DIR / "skill-quality-check.py",
)
assert _spec is not None and _spec.loader is not None
_mod = _ilu.module_from_spec(_spec)
_spec.loader.exec_module(_mod)

parse_frontmatter = _mod.parse_frontmatter
check_skill = _mod.check_skill


# ---------------------------------------------------------------------------
# 1. parse_frontmatter — 정상 frontmatter (description 포함)
# ---------------------------------------------------------------------------


def test_parse_frontmatter_valid():
    """정상 frontmatter 파싱 시 description 필드가 포함된 dict를 반환해야 한다."""
    text = """\
---
name: my-skill
description: 테스트용 스킬 설명
version: 1.0
---
본문 내용
"""
    result = parse_frontmatter(text)
    assert result is not None
    assert isinstance(result, dict)
    assert "description" in result
    assert result["description"] == "테스트용 스킬 설명"
    assert result["name"] == "my-skill"


# ---------------------------------------------------------------------------
# 2. parse_frontmatter — description 누락
# ---------------------------------------------------------------------------


def test_parse_frontmatter_no_description():
    """description이 없는 frontmatter 파싱 시 dict에 description 키가 없어야 한다."""
    text = """\
---
name: no-desc-skill
version: 2.0
---
본문
"""
    result = parse_frontmatter(text)
    assert result is not None
    assert isinstance(result, dict)
    assert "description" not in result
    assert result["name"] == "no-desc-skill"


# ---------------------------------------------------------------------------
# 3. parse_frontmatter — frontmatter 자체가 없는 경우
# ---------------------------------------------------------------------------


def test_parse_frontmatter_none():
    """frontmatter 구분자(---)가 없는 텍스트는 None을 반환해야 한다."""
    text = "그냥 본문만 있는 마크다운 파일입니다."
    result = parse_frontmatter(text)
    assert result is None


# ---------------------------------------------------------------------------
# 4. check_skill — SKILL.md + 유효 frontmatter + registry 등록 → PASS
# ---------------------------------------------------------------------------


def test_check_skill_pass(tmp_path: Path):
    """SKILL.md 존재 + 유효 frontmatter + registry 등록 시 verdict가 PASS여야 한다."""
    skill_name = "my-test-skill"
    skill_dir = tmp_path / skill_name
    skill_dir.mkdir()

    skill_md = skill_dir / "SKILL.md"
    skill_md.write_text(
        "---\nname: my-test-skill\ndescription: 테스트 설명\n---\n본문\n",
        encoding="utf-8",
    )

    registry = {skill_name: {"name": skill_name}}
    eval_axes = {}

    result = check_skill(skill_name, skill_dir, registry, eval_axes)

    assert result.verdict == "PASS"
    assert result.has_skill_md is True
    assert result.frontmatter_valid is True
    assert result.registry_synced is True


# ---------------------------------------------------------------------------
# 5. check_skill — SKILL.md 없음 → FAIL
# ---------------------------------------------------------------------------


def test_check_skill_fail_no_skillmd(tmp_path: Path):
    """SKILL.md가 없는 디렉토리는 verdict가 FAIL이어야 한다."""
    skill_name = "missing-skillmd"
    skill_dir = tmp_path / skill_name
    skill_dir.mkdir()
    # SKILL.md를 생성하지 않음

    registry = {skill_name: {"name": skill_name}}
    eval_axes = {}

    result = check_skill(skill_name, skill_dir, registry, eval_axes)

    assert result.verdict == "FAIL"
    assert result.has_skill_md is False


# ---------------------------------------------------------------------------
# 6. check_skill — SKILL.md 있지만 registry 미등록 → WARN
# ---------------------------------------------------------------------------


def test_check_skill_warn_no_registry(tmp_path: Path):
    """SKILL.md는 존재하지만 registry에 미등록 시 verdict가 WARN이어야 한다."""
    skill_name = "unregistered-skill"
    skill_dir = tmp_path / skill_name
    skill_dir.mkdir()

    skill_md = skill_dir / "SKILL.md"
    skill_md.write_text(
        "---\nname: unregistered-skill\ndescription: 설명 있음\n---\n본문\n",
        encoding="utf-8",
    )

    # registry에 해당 스킬 없음
    registry = {}
    eval_axes = {}

    result = check_skill(skill_name, skill_dir, registry, eval_axes)

    assert result.verdict == "WARN"
    assert result.has_skill_md is True
    assert result.frontmatter_valid is True
    assert result.registry_synced is False


# ---------------------------------------------------------------------------
# 7. --summary 모드 실행 (subprocess)
# ---------------------------------------------------------------------------


def test_summary_runs():
    """--summary 옵션으로 스크립트를 실행했을 때 정상 출력(exit 0 또는 1)이 나와야 한다."""
    script_path = str(_SCRIPTS_DIR / "skill-quality-check.py")
    proc = subprocess.run(
        [sys.executable, script_path, "--summary"],
        capture_output=True,
        text=True,
        timeout=30,
    )

    # exit code는 0(PASS/WARN만) 또는 1(FAIL 존재) 모두 허용
    assert proc.returncode in (0, 1), (
        f"예상치 못한 exit code: {proc.returncode}\n"
        f"stdout: {proc.stdout}\nstderr: {proc.stderr}"
    )

    # 요약 헤더가 출력에 포함되어야 함
    combined = proc.stdout + proc.stderr
    assert "스킬 품질 검증 요약" in combined, (
        f"요약 헤더가 출력에 없음.\nstdout: {proc.stdout}\nstderr: {proc.stderr}"
    )
