"""스킬 SKILL.md frontmatter 파싱 및 메타데이터 추출.

skill_loader.py의 파싱 로직을 분리한 모듈이다.
3계층 Progressive Disclosure 로더에서 사용하는 파싱 함수를 제공한다.

Public API:
    parse_frontmatter(content) -> tuple[dict, str]
    extract_description(fm, body) -> str
    extract_triggers(fm, body) -> list[str]
    extract_requires(fm) -> list[str]
    extract_category(fm, body, skill_name) -> str
"""

from __future__ import annotations

import re
from typing import Any

# PyYAML은 선택적 import
try:
    import yaml as _yaml_module

    _YAML_AVAILABLE = True
except ImportError:
    _yaml_module = None  # type: ignore[assignment]
    _YAML_AVAILABLE = False

_FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
_HEADING_RE = re.compile(r"^#\s+(.+)$", re.MULTILINE)
_TRIGGER_LINE_RE = re.compile(r"(?:trigger|use when)", re.IGNORECASE)
_CATEGORY_LINE_RE = re.compile(r"category\s*[:=]\s*(.+)", re.IGNORECASE)


def parse_frontmatter(content: str) -> tuple[dict[str, Any], str]:
    """YAML frontmatter를 파싱한다.

    Args:
        content: SKILL.md 전체 내용.

    Returns:
        (frontmatter_dict, body_without_frontmatter).
        YAML 없거나 파싱 실패 시 ({}, content).
    """
    match = _FRONTMATTER_RE.match(content)
    if not match:
        return {}, content

    raw_fm = match.group(1)
    body = content[match.end() :]

    if not _YAML_AVAILABLE:
        # YAML 없으면 간단한 key: value 파싱
        fm: dict[str, Any] = {}
        for line in raw_fm.splitlines():
            if ":" in line and not line.strip().startswith("-"):
                k, _, v = line.partition(":")
                k = k.strip()
                v = v.strip().strip('"').strip("'")
                if k and v:
                    fm[k] = v
        return fm, body

    if _yaml_module is None:
        return {}, body
    try:
        parsed = _yaml_module.safe_load(raw_fm)
        if isinstance(parsed, dict):
            return parsed, body
        return {}, body
    except Exception:
        return {}, body


def extract_description(fm: dict[str, Any], body: str) -> str:
    """frontmatter 또는 첫 번째 # 헤딩에서 설명을 추출한다.

    Args:
        fm: parse_frontmatter 로 얻은 frontmatter dict.
        body: frontmatter를 제거한 본문.

    Returns:
        설명 문자열. 없으면 빈 문자열.
    """
    desc = fm.get("description", "")
    if desc:
        return str(desc).strip()

    match = _HEADING_RE.search(body)
    if match:
        return match.group(1).strip()

    return ""


def extract_triggers(fm: dict[str, Any], body: str) -> list[str]:
    """frontmatter triggers 또는 본문에서 트리거를 추출한다.

    Args:
        fm: parse_frontmatter 로 얻은 frontmatter dict.
        body: frontmatter를 제거한 본문.

    Returns:
        트리거 문자열 목록.
    """
    for key in ("triggers", "trigger"):
        val = fm.get(key)
        if val is None:
            continue
        if isinstance(val, list):
            return [str(t).strip() for t in val if t]
        if isinstance(val, str):
            return [val.strip()]

    # 본문에서 "trigger" 또는 "Use when" 포함 줄 추출
    result: list[str] = []
    for line in body.splitlines():
        if _TRIGGER_LINE_RE.search(line):
            cleaned = line.lstrip("#-*> ").strip()
            if cleaned:
                result.append(cleaned)
    return result


def extract_requires(fm: dict[str, Any]) -> list[str]:
    """frontmatter의 requires/prerequisites를 추출한다.

    Args:
        fm: parse_frontmatter 로 얻은 frontmatter dict.

    Returns:
        의존성 문자열 목록.
    """
    for key in ("requires", "prerequisites"):
        val = fm.get(key)
        if val is None:
            continue
        if isinstance(val, list):
            return [str(r).strip() for r in val if r]
        if isinstance(val, str):
            return [val.strip()]
    return []


def extract_category(fm: dict[str, Any], body: str, skill_name: str) -> str:
    """frontmatter category 또는 본문에서 카테고리를 추출한다.

    Args:
        fm: parse_frontmatter 로 얻은 frontmatter dict.
        body: frontmatter를 제거한 본문.
        skill_name: 폴백용 스킬 이름 (현재 사용 안 함, 확장 여지 보존).

    Returns:
        카테고리 문자열. 없으면 'general'.
    """
    cat = fm.get("category", "")
    if cat:
        return str(cat).strip()

    match = _CATEGORY_LINE_RE.search(body)
    if match:
        return match.group(1).strip().strip('"').strip("'")

    return "general"
