#!/usr/bin/env python3
"""
Skill Scanner — Hermes 风格技能发现系统

扫描 skills/ 下所有 SKILL.md，解析 frontmatter，生成技能索引注入 prompt.md。
支持 agentskills.io 开放标准兼容。

用法：
  python3 scripts/skill_scanner.py              # 扫描并生成索引
  python3 scripts/skill_scanner.py --json        # JSON 输出
  python3 scripts/skill_scanner.py --inject      # 注入到 prompt.md
"""

import json
import os
import re
import sys
from pathlib import Path

PROJECT_DIR = Path(__file__).parent.parent
SKILLS_DIR = PROJECT_DIR / "skills"
PROMPT_FILE = PROJECT_DIR / ".opencode" / "prompt.md"

def parse_frontmatter(content):
    """解析 YAML frontmatter"""
    if not content.startswith("---"):
        return {}

    m = re.match(r'^---\s*\n(.*?)\n---', content, re.DOTALL)
    if not m:
        return {}

    meta = {}
    for line in m.group(1).splitlines():
        line = line.strip()
        if ':' in line:
            key, _, val = line.partition(':')
            meta[key.strip()] = val.strip().strip('"').strip("'")
    return meta

def scan_skills():
    """扫描所有技能并返回索引"""
    skills = []
    if not SKILLS_DIR.exists():
        return skills

    for skill_dir in sorted(SKILLS_DIR.iterdir()):
        if not skill_dir.is_dir():
            continue
        skill_md = skill_dir / "SKILL.md"
        if not skill_md.exists():
            continue

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

        meta = parse_frontmatter(content)

        # 提取描述（frontmatter > 第一段非标题文本）
        description = meta.get("description", "")
        if not description:
            lines = content.splitlines()
            in_frontmatter = False
            frontmatter_closed = False
            # 跳过 frontmatter 和标题，提取第一段有意义的文本
            found_title = False
            for line in lines:
                if line.strip() == "---":
                    if not frontmatter_closed:
                        in_frontmatter = not in_frontmatter
                        if not in_frontmatter:
                            frontmatter_closed = True
                        continue
                if in_frontmatter:
                    continue
                stripped = line.strip()
                if not stripped:
                    continue
                if stripped.startswith("#"):
                    found_title = True
                    continue
                if stripped.startswith(">") or stripped.startswith("```"):
                    continue
                if stripped.startswith("|"):
                    continue
                # 找到了第一段描述文字
                description = stripped[:120]
                break

        name = meta.get("name", skill_dir.name)
        category = meta.get("category", meta.get("tags", "general"))
        version = meta.get("version", "1.0.0")
        platforms = meta.get("platforms", "")

        skills.append({
            "name": name,
            "slug": f"/{skill_dir.name}",
            "category": category,
            "version": version,
            "platforms": platforms,
            "description": description,
            "path": str(skill_dir.relative_to(PROJECT_DIR)),
            "file": str(skill_md.relative_to(PROJECT_DIR))
        })

    return skills

def generate_index(skills):
    """生成技能索引文本"""
    lines = [
        "## 🤖 技能索引 (auto-generated by skill_scanner.py)",
        "",
        f"共 {len(skills)} 个技能：",
        ""
    ]

    for s in skills:
        name = s['name']
        slug = s['slug']
        desc = s['description']
        cat = s.get('category', '')
        ver = s.get('version', '')
        lines.append(f"| `{slug}` | **{name}** | {desc[:80]} | {cat} | v{ver} |")

    lines.append("")
    lines.append("> 使用 `/<skill-name>` 调用技能，或通过 tool 加载 `skills/<name>/SKILL.md`")
    lines.append("> 索引更新时间：自动")
    return "\n".join(lines)

def inject_to_prompt(index_text):
    """注入索引到 prompt.md"""
    if not PROMPT_FILE.exists():
        print(f"[FAIL] prompt.md 不存在: {PROMPT_FILE}")
        return False

    content = PROMPT_FILE.read_text(encoding="utf-8")

    # 替换或追加技能索引段
    marker_start = "## 🤖 技能索引 (auto-generated by skill_scanner.py)"
    marker_end = "> 索引更新时间"

    if marker_start in content:
        # 替换现有索引
        parts = content.split(marker_start, 1)
        prefix = parts[0]
        suffix = parts[1] if len(parts) > 1 else ""
        # 找到下一个 ## 或文件结尾
        next_section = re.search(r'\n## ', suffix)
        if next_section:
            suffix = suffix[next_section.start():]
        else:
            # 找到 marker_end 之后的内容
            end_pos = suffix.find(marker_end)
            if end_pos != -1:
                end_line = suffix.find('\n', end_pos)
                suffix = suffix[end_line+1:] if end_line != -1 else ""

        new_content = prefix.rstrip() + "\n\n" + index_text + suffix
    else:
        # 追加到文件末尾
        new_content = content.rstrip() + "\n\n" + index_text + "\n"

    PROMPT_FILE.write_text(new_content, encoding="utf-8")
    return True

def main():
    skills = scan_skills()

    if not skills:
        print("[INFO] 未找到技能文件。")
        return

    if "--json" in sys.argv:
        print(json.dumps(skills, ensure_ascii=False, indent=2))
        return

    print(f"📚 技能扫描完成 — 共 {len(skills)} 个技能:\n")
    for s in skills:
        print(f"  {s['slug']} — {s['name']}")
        print(f"    类别: {s['category']} | v{s['version']}")
        print(f"    描述: {s['description'][:100]}")
        print()

    index_text = generate_index(skills)

    if "--inject" in sys.argv:
        if inject_to_prompt(index_text):
            print("[OK] 技能索引已注入 prompt.md")

    print("\n--- 技能索引预览 ---")
    print(index_text)

if __name__ == "__main__":
    main()
