"""스킬 3계층 Progressive Disclosure 로더.

SKILL.md 기반 스킬을 3단계로 로드한다:
  1. list  → 이름 + 1줄 설명 (SkillSummary)
  2. view  → 설명 + 트리거 + 의존성 (SkillDetail)
  3. load  → SKILL.md 전체 내용 (str)

SKILL.md 포맷:
    ---                                   ← YAML frontmatter (선택)
    name: skill-name
    description: 1줄 설명
    triggers:
      - "trigger1"
    requires:
      - "dependency"
    category: general
    ---

    # Skill Title                         ← 첫 번째 헤딩 (frontmatter 없을 때 설명으로 사용)

    본문 내용...

Usage:
    from utils.skill_loader import list_skills, view_skill, load_skill
    summaries = list_skills("/home/jay/workspace/skills")
    detail = view_skill("/home/jay/workspace/skills", "retro")
    content = load_skill("/home/jay/workspace/skills", "pdf")
"""

from __future__ import annotations

from dataclasses import dataclass, field
from enum import Enum
from pathlib import Path

from utils.skill_parser import (
    extract_category,
    extract_description,
    extract_requires,
    extract_triggers,
    parse_frontmatter,
)


@dataclass
class SkillSummary:
    """스킬 1계층: 이름 + 1줄 설명 (목록 표시용)."""

    name: str
    description: str
    category: str = "general"


@dataclass
class SkillDetail:
    """스킬 2계층: 설명 + 트리거 + 의존성 (상세 뷰)."""

    name: str
    description: str
    triggers: list[str] = field(default_factory=list)
    requires: list[str] = field(default_factory=list)
    full_path: str = ""


def _skill_md_path(skills_dir: Path, name: str) -> Path:
    """스킬 이름으로 SKILL.md 경로를 반환한다."""
    return skills_dir / name / "SKILL.md"


def list_skills(skills_dir: str | Path) -> list[SkillSummary]:
    """스킬 디렉토리에서 모든 스킬의 요약을 반환한다 (1계층).

    SKILL.md 파일이 있는 직접 하위 디렉토리만 스캔한다.

    Args:
        skills_dir: 스킬 디렉토리 경로.

    Returns:
        SkillSummary 목록 (이름 오름차순).
    """
    base = Path(skills_dir)
    if not base.exists() or not base.is_dir():
        return []

    summaries: list[SkillSummary] = []
    for entry in sorted(base.iterdir()):
        if not entry.is_dir():
            continue
        skill_md = entry / "SKILL.md"
        if not skill_md.exists():
            continue

        try:
            content = skill_md.read_text(encoding="utf-8")
        except OSError:
            continue

        fm, body = parse_frontmatter(content)
        name = fm.get("name") or entry.name
        description = extract_description(fm, body)
        category = extract_category(fm, body, entry.name)

        summaries.append(
            SkillSummary(
                name=str(name),
                description=description,
                category=category,
            )
        )

    return summaries


def view_skill(skills_dir: str | Path, name: str) -> SkillDetail:
    """특정 스킬의 상세 정보를 반환한다 (2계층).

    Args:
        skills_dir: 스킬 디렉토리 경로.
        name: 스킬 이름 (디렉토리 이름).

    Returns:
        SkillDetail (설명 + 트리거 + 의존성).

    Raises:
        FileNotFoundError: 스킬이 존재하지 않는 경우.
    """
    base = Path(skills_dir)
    skill_md = _skill_md_path(base, name)

    if not skill_md.exists():
        raise FileNotFoundError(f"스킬 '{name}' 없음: {skill_md}")

    content = skill_md.read_text(encoding="utf-8")
    fm, body = parse_frontmatter(content)

    skill_name = fm.get("name") or name
    description = extract_description(fm, body)
    triggers = extract_triggers(fm, body)
    requires = extract_requires(fm)

    return SkillDetail(
        name=str(skill_name),
        description=description,
        triggers=triggers,
        requires=requires,
        full_path=str(skill_md.resolve()),
    )


def load_skill(skills_dir: str | Path, name: str) -> str:
    """특정 스킬의 SKILL.md 전체 내용을 반환한다 (3계층).

    Args:
        skills_dir: 스킬 디렉토리 경로.
        name: 스킬 이름 (디렉토리 이름).

    Returns:
        SKILL.md 전체 텍스트.

    Raises:
        FileNotFoundError: 스킬이 존재하지 않는 경우.
    """
    base = Path(skills_dir)
    skill_md = _skill_md_path(base, name)

    if not skill_md.exists():
        raise FileNotFoundError(f"스킬 '{name}' 없음: {skill_md}")

    return skill_md.read_text(encoding="utf-8")


# ---------------------------------------------------------------------------
# Progressive Disclosure: SkillLevel, 분류 config
# ---------------------------------------------------------------------------


class SkillLevel(Enum):
    """스킬 로드 우선순위 레벨."""

    CORE = "core"  # 항상 로드 (보안, 핵심 워크플로우)
    STANDARD = "standard"  # 키워드 트리거 시 로드
    EXTENDED = "extended"  # 명시적 호출 시만 로드


SECURITY_WHITELIST: frozenset[str] = frozenset(
    {
        "nuclear-approval",
        "verification-before-completion",
        "systematic-debugging",
        "tdd-enforcement",
        "qc-rules",
    }
)

KEYWORD_TRIGGERS: dict[str, list[str]] = {
    "blog-writer": ["블로그", "blog", "포스팅"],
    "pdf": ["pdf", "PDF", ".pdf"],
    "seo-audit": ["seo", "SEO", "검색엔진"],
    "frontend-design": ["프론트엔드", "frontend", "UI", "웹 디자인"],
    "copywriting": ["카피", "copy", "카피라이팅"],
    "naver-seo": ["네이버", "naver", "DataLab"],
    "fullstack-builder": ["풀스택", "fullstack", "SaaS", "랜딩"],
    "canvas-design": ["포스터", "일러스트", "그래픽"],
    "docx": ["word", "Word", "docx", ".docx"],
    "gemini-image": ["이미지 생성", "gemini", "포토리얼"],
    "webapp-testing": ["playwright", "브라우저 테스트", "웹 테스트"],
    "advanced-crawling": ["크롤링", "스크래핑", "crawl"],
    "book-writer": ["집필", "소설", "원고", "책 쓰기"],
    "competitor-analyst": ["경쟁사", "competitor", "역분석"],
    "pricing-strategy": ["가격", "pricing", "요금"],
    "research-prompt": ["리서치", "연구", "논문"],
    "strategy-prompt": ["전략", "90일", "KPI"],
    "marketing-strategist": ["마케팅 전략", "캠페인", "콘텐츠 캘린더"],
    "agent-meeting": ["미팅", "페르소나", "의견 수집"],
    "retro": ["회고", "retrospective", "retro"],
}

# 보안 관련 스킬 감지에 사용할 키워드
_SECURITY_DETECT_KEYWORDS: tuple[str, ...] = (
    "security",
    "보안",
    "audit",
    "red-team",
)

# ---------------------------------------------------------------------------
# Feature flag: Progressive Disclosure 마스터 스위치
# ---------------------------------------------------------------------------

_PROGRESSIVE_DISCLOSURE_ENABLED: bool = True


def set_progressive_disclosure(enabled: bool) -> None:
    """Progressive Disclosure 기능 토글. False이면 모든 스킬을 CORE로 취급."""
    global _PROGRESSIVE_DISCLOSURE_ENABLED
    _PROGRESSIVE_DISCLOSURE_ENABLED = enabled


def is_progressive_disclosure_enabled() -> bool:
    """Progressive Disclosure 활성화 여부를 반환한다."""
    return _PROGRESSIVE_DISCLOSURE_ENABLED


# ---------------------------------------------------------------------------
# 스킬 분류 함수
# ---------------------------------------------------------------------------


def classify_skill(name: str) -> SkillLevel:
    """스킬 이름을 CORE / STANDARD / EXTENDED 중 하나로 분류한다."""
    if not _PROGRESSIVE_DISCLOSURE_ENABLED:
        return SkillLevel.CORE
    if name in SECURITY_WHITELIST:
        return SkillLevel.CORE
    if name in KEYWORD_TRIGGERS:
        return SkillLevel.STANDARD
    return SkillLevel.EXTENDED


# ---------------------------------------------------------------------------
# 프롬프트 기반 스킬 매칭
# ---------------------------------------------------------------------------


def match_skills_by_prompt(prompt: str, skills_dir: str | Path) -> list[SkillSummary]:
    """사용자 프롬프트에서 KEYWORD_TRIGGERS를 매칭해 SkillSummary 목록을 반환한다."""
    prompt_lower = prompt.lower()
    matched_names: list[str] = []

    for skill_name, keywords in KEYWORD_TRIGGERS.items():
        for kw in keywords:
            if kw.lower() in prompt_lower:
                matched_names.append(skill_name)
                break  # 한 스킬에서 중복 추가 방지

    if not matched_names:
        return []

    all_summaries = list_skills(skills_dir)
    name_to_summary = {s.name: s for s in all_summaries}

    result: list[SkillSummary] = []
    for name in matched_names:
        summary = name_to_summary.get(name)
        if summary is not None:
            result.append(summary)

    return result


# ---------------------------------------------------------------------------
# 레벨별 스킬 조회
# ---------------------------------------------------------------------------


def get_skills_by_level(skills_dir: str | Path, level: SkillLevel) -> list[SkillSummary]:
    """주어진 SkillLevel에 해당하는 스킬의 SkillSummary 목록을 반환한다."""
    return [s for s in list_skills(skills_dir) if classify_skill(s.name) == level]


# ---------------------------------------------------------------------------
# 보안 화이트리스트 검증
# ---------------------------------------------------------------------------


def check_security_whitelist(skills_dir: str | Path) -> list[str]:
    """보안 관련이지만 화이트리스트에 미등록된 스킬을 감지하여 경고 목록 반환."""
    warnings: list[str] = []

    for summary in list_skills(skills_dir):
        if summary.name in SECURITY_WHITELIST:
            continue  # 이미 등록된 스킬은 건너뜀

        combined = f"{summary.name} {summary.description}".lower()
        if any(kw in combined for kw in _SECURITY_DETECT_KEYWORDS):
            warnings.append(summary.name)

    return warnings
