"""
SkillLoader - 動態技能載入器
==============================

Phase 6.4f: 實作 Skill 動態載入

功能:
1. 載入 .agents/skills/*.md 的技能定義
2. 解析 Frontmatter 提取 metadata
3. 提供 LLM Context 注入

使用方式:
    loader = SkillLoader(skills_dir=".agents/skills")
    content = loader.load("04-awoooi-devops-commander")

    # 或批次載入
    all_skills = loader.load_all()
"""

import os
import re
from pathlib import Path
from typing import Any
from dataclasses import dataclass, field


# =============================================================================
# Skill Data Structures
# =============================================================================

@dataclass
class Skill:
    """技能定義"""
    skill_id: str
    name: str
    description: str
    content: str
    triggers: list[str] = field(default_factory=list)
    metadata: dict[str, Any] = field(default_factory=dict)

    def to_context(self) -> str:
        """轉換為 LLM Context 格式"""
        return f"""## Skill: {self.name}

{self.description}

---

{self.content}
"""


# =============================================================================
# SkillLoader Implementation
# =============================================================================

class SkillLoader:
    """
    技能載入器

    職責:
    1. 掃描 skills 目錄下的 .md 檔案
    2. 解析 Frontmatter 提取 metadata
    3. 提供按 ID 或批次載入

    目錄結構:
        .agents/skills/
        ├── 01-awoooi-frontend-aesthetics.md
        ├── 02-lewooogo-backend-core.md
        ├── 03-openclaw-cognitive-expert.md
        ├── 04-awoooi-devops-commander.md
        ├── 05-awoooi-sre-qa.md
        └── 06-awoooi-monorepo-master.md
    """

    def __init__(
        self,
        skills_dir: str | Path = ".agents/skills",
        project_root: str | Path | None = None,
    ):
        """
        初始化 SkillLoader

        Args:
            skills_dir: Skills 目錄相對路徑
            project_root: 專案根目錄 (自動偵測如果未指定)
        """
        if project_root:
            self._skills_path = Path(project_root) / skills_dir
        else:
            # 嘗試從當前目錄向上尋找 .agents/skills
            self._skills_path = self._find_skills_dir(skills_dir)

        self._cache: dict[str, Skill] = {}

    def _find_skills_dir(self, skills_dir: str) -> Path:
        """尋找 skills 目錄"""
        current = Path.cwd()

        # 向上搜尋最多 5 層
        for _ in range(5):
            candidate = current / skills_dir
            if candidate.exists() and candidate.is_dir():
                return candidate
            current = current.parent

        # 預設使用相對路徑
        return Path(skills_dir)

    def load(self, skill_id: str) -> str | None:
        """
        載入單一技能內容

        Args:
            skill_id: 技能 ID (e.g., "04-awoooi-devops-commander" 或 "04")

        Returns:
            str | None: 技能內容 (Markdown) 或 None
        """
        skill = self.load_skill(skill_id)
        return skill.content if skill else None

    def load_skill(self, skill_id: str) -> Skill | None:
        """
        載入單一技能物件

        Args:
            skill_id: 技能 ID

        Returns:
            Skill | None: 技能物件或 None
        """
        # 檢查快取
        if skill_id in self._cache:
            return self._cache[skill_id]

        # 尋找匹配的檔案
        file_path = self._find_skill_file(skill_id)
        if not file_path:
            return None

        # 解析檔案
        skill = self._parse_skill_file(file_path)
        if skill:
            self._cache[skill.skill_id] = skill
            # 也用短 ID 快取
            short_id = skill_id.split("-")[0] if "-" in skill_id else skill_id
            self._cache[short_id] = skill

        return skill

    def load_all(self) -> list[Skill]:
        """
        載入所有技能

        Returns:
            list[Skill]: 所有技能列表
        """
        skills = []

        if not self._skills_path.exists():
            return skills

        for file_path in sorted(self._skills_path.glob("*.md")):
            skill = self._parse_skill_file(file_path)
            if skill:
                skills.append(skill)
                self._cache[skill.skill_id] = skill

        return skills

    def get_context_for_incident(
        self,
        affected_services: list[str],
        severity: str,
    ) -> str:
        """
        根據 Incident 特徵自動選擇相關 Skills

        Args:
            affected_services: 受影響的服務列表
            severity: 嚴重等級

        Returns:
            str: 組合的 Skills Context
        """
        relevant_skills = []

        # 載入所有技能
        all_skills = self.load_all()

        for skill in all_skills:
            # 檢查觸發條件
            for trigger in skill.triggers:
                trigger_lower = trigger.lower()

                # 服務名稱匹配
                for service in affected_services:
                    if service.lower() in trigger_lower:
                        relevant_skills.append(skill)
                        break

                # 嚴重度匹配 (P0/P1 → DevOps, SRE)
                if severity in ["P0", "P1"]:
                    if "devops" in trigger_lower or "sre" in trigger_lower:
                        relevant_skills.append(skill)
                        break

        # 去重
        seen = set()
        unique_skills = []
        for skill in relevant_skills:
            if skill.skill_id not in seen:
                seen.add(skill.skill_id)
                unique_skills.append(skill)

        # 組合 Context
        if not unique_skills:
            # 預設使用 DevOps + SRE
            devops = self.load_skill("04")
            sre = self.load_skill("05")
            unique_skills = [s for s in [devops, sre] if s]

        return "\n\n---\n\n".join([s.to_context() for s in unique_skills])

    def list_skills(self) -> list[dict[str, str]]:
        """
        列出所有可用技能

        Returns:
            list[dict]: 技能摘要列表
        """
        skills = self.load_all()
        return [
            {
                "skill_id": s.skill_id,
                "name": s.name,
                "description": s.description,
            }
            for s in skills
        ]

    # =========================================================================
    # Private Methods
    # =========================================================================

    def _find_skill_file(self, skill_id: str) -> Path | None:
        """尋找技能檔案"""
        if not self._skills_path.exists():
            return None

        # 完整 ID 匹配
        for file_path in self._skills_path.glob("*.md"):
            filename = file_path.stem
            if filename == skill_id:
                return file_path

        # 短 ID 匹配 (e.g., "04" → "04-awoooi-devops-commander")
        short_id = skill_id.split("-")[0] if "-" in skill_id else skill_id
        for file_path in self._skills_path.glob("*.md"):
            filename = file_path.stem
            if filename.startswith(f"{short_id}-"):
                return file_path

        return None

    def _parse_skill_file(self, file_path: Path) -> Skill | None:
        """解析技能檔案"""
        try:
            content = file_path.read_text(encoding="utf-8")

            # 提取標題 (第一個 # 開頭的行)
            name_match = re.search(r'^#\s+(.+)$', content, re.MULTILINE)
            name = name_match.group(1) if name_match else file_path.stem

            # 提取描述 (第二個 # 開頭的行，通常是中文標題)
            desc_match = re.search(r'^#\s+(.+)\n#\s+(.+)$', content, re.MULTILINE)
            description = desc_match.group(2) if desc_match else ""

            # 提取觸發條件 (> **觸發條件**: ...)
            trigger_match = re.search(r'觸發條件[：:]\s*(.+?)(?:\n|$)', content)
            triggers = []
            if trigger_match:
                trigger_text = trigger_match.group(1)
                # 解析觸發條件 (逗號分隔或 `` 包裹的檔案模式)
                triggers = re.findall(r'`([^`]+)`', trigger_text)

            # 提取管轄範圍
            scope_match = re.search(r'管轄範圍[：:]\s*(.+?)(?:\n|$)', content)
            scope = scope_match.group(1) if scope_match else ""

            # 構建 Skill ID
            skill_id = file_path.stem

            return Skill(
                skill_id=skill_id,
                name=name,
                description=description or scope,
                content=content,
                triggers=triggers,
                metadata={
                    "file_path": str(file_path),
                    "scope": scope,
                },
            )

        except Exception as e:
            # 靜默處理錯誤
            return None


# =============================================================================
# 便捷函數
# =============================================================================

_default_loader: SkillLoader | None = None


def get_skill_loader() -> SkillLoader:
    """取得預設 SkillLoader 實例"""
    global _default_loader
    if _default_loader is None:
        _default_loader = SkillLoader()
    return _default_loader


def load_skill(skill_id: str) -> str | None:
    """快速載入技能內容"""
    return get_skill_loader().load(skill_id)


def load_skill_context(
    affected_services: list[str],
    severity: str,
) -> str:
    """根據 Incident 自動載入相關 Skill Context"""
    return get_skill_loader().get_context_for_incident(affected_services, severity)
