"""
SKILL.md 加载器（服务端版）
==========================

本模块负责解析和加载 SKILL.md 格式的技能文件。

当前服务端实现约束
------------------
1. 仅使用**用户级技能目录**：
   - 固定目录：`skill/server_skill`
   - 目录结构：`skill/server_skill/{skill_name}/SKILL.md`
2. 暂不支持 Project 级技能目录覆盖
3. 主要被 `ServerSkillsMiddleware` 调用，为 Agent 提供技能清单
4. 需要记录关键操作的耗时，便于线上诊断

本模块为 langchain_agentx 内部实现，不依赖 langchain_agentx 以外的代码。
"""
import re
import time
import logging
from pathlib import Path
from typing import TypedDict, NotRequired, List

logger = logging.getLogger(__name__)


class SkillMetadata(TypedDict):
    """
    技能元数据（服务端精简版）

    标准字段（必需）：
        name: 技能名称
        description: 技能描述
        path: SKILL.md 文件路径
        source: 来源（服务端固定为 "user"）

    扩展字段（可选）：
        tool_groups: 引用的 ToolGroup 列表（用于在技能列表中提示 Agent）
    """
    # 标准字段
    name: str
    description: str
    path: str
    source: str  # 服务端固定为 "user"

    # 扩展字段
    tool_groups: NotRequired[List[str]]  # 引用的工具组列表，用于系统提示


def parse_skill_metadata(
    skill_md_path: Path,
    source: str
) -> SkillMetadata | None:
    """
    解析 SKILL.md 的 YAML frontmatter

    Args:
        skill_md_path: SKILL.md 文件路径
        source: 技能来源（"user" 或 "project"）

    Returns:
        SkillMetadata 或 None（如果解析失败）

    支持的 YAML 格式：
        - 简单键值对：key: value
        - 列表：
          key:
            - item1
            - item2
    """
    try:
        content = skill_md_path.read_text(encoding="utf-8")

        # 匹配 YAML frontmatter (--- ... ---)
        frontmatter_pattern = r"^---\s*\n(.*?)\n---\s*\n"
        match = re.match(frontmatter_pattern, content, re.DOTALL)

        if not match:
            return None

        frontmatter = match.group(1)

        # 解析 YAML（简单实现）
        metadata = {}
        current_list_key = None
        current_list = []

        for line in frontmatter.split("\n"):
            line = line.strip()

            # 跳过注释和空行
            if not line or line.startswith("#"):
                continue

            # 处理列表项
            if line.startswith("- ") and current_list_key:
                current_list.append(line[2:].strip())
                continue

            # 保存上一个列表
            if current_list_key and not line.startswith("- "):
                metadata[current_list_key] = current_list
                current_list_key = None
                current_list = []

            # 匹配 "key: value"
            kv_match = re.match(r"^(\w+):\s*(.*)$", line)
            if kv_match:
                key, value = kv_match.groups()
                value = value.strip()

                # 检查是否是列表开始
                if not value:
                    current_list_key = key
                    current_list = []
                else:
                    metadata[key] = value

        # 保存最后的列表
        if current_list_key:
            metadata[current_list_key] = current_list

        # 验证必需字段
        if "name" not in metadata or "description" not in metadata:
            return None

        # 构建 SkillMetadata
        skill_meta: SkillMetadata = {
            "name": metadata["name"],
            "description": metadata["description"],
            "path": str(skill_md_path),
            "source": source,
        }

        # 添加可选字段（仅保留 tool_groups，其他字段在 SKILL.md 中）
        if "tool_groups" in metadata:
            skill_meta["tool_groups"] = metadata["tool_groups"]

        return skill_meta

    except (OSError, UnicodeDecodeError):
        return None


def list_skills(skills_dir: Path) -> List[SkillMetadata]:
    """
    列出技能目录中的所有技能（服务端简化版）

    服务端实现约束：
        - 仅使用固定目录：`skill/server_skill`
        - 不支持 Project 级技能目录覆盖
        - 所有技能的 source 字段固定为 "user"

    Args:
        skills_dir: 技能目录路径（例如 `skill/server_skill`）

    Returns:
        技能元数据列表

    目录结构要求：
        skills_dir/
        ├── skill1/
        │   └── SKILL.md
        ├── skill2/
        │   └── SKILL.md
        └── ...
    """
    start_ts = time.perf_counter()

    # 加载技能（服务端实现中所有技能都标记为 "user"）
    skills_list = _list_skills_from_dir(skills_dir, source="user")

    duration_ms = (time.perf_counter() - start_ts) * 1000
    logger.info(
        "list_skills completed: total=%d, skills_dir=%s, duration=%.2f ms",
        len(skills_list),
        str(skills_dir),
        duration_ms,
    )
    return skills_list


def _list_skills_from_dir(
    skills_dir: Path,
    source: str
) -> List[SkillMetadata]:
    """
    从目录加载技能

    Args:
        skills_dir: 技能目录
        source: 技能来源（"user" 或 "project"）

    Returns:
        技能元数据列表
    """
    skills_dir = skills_dir.expanduser()
    if not skills_dir.exists():
        return []

    skills: List[SkillMetadata] = []

    for skill_dir in skills_dir.iterdir():
        if not skill_dir.is_dir():
            continue

        skill_md_path = skill_dir / "SKILL.md"
        if not skill_md_path.exists():
            continue

        metadata = parse_skill_metadata(skill_md_path, source=source)
        if metadata:
            skills.append(metadata)

    return skills
