#!/usr/bin/env python3
"""
Scan .opencode/skills directory and extract skill metadata.
"""

import re
from pathlib import Path
from typing import Dict, List
try:
    import yaml
except ModuleNotFoundError:
    raise SystemExit(
        "PyYAML is required. Install with: python3 -m pip install -r .opencode/scripts/requirements.txt"
    )

# Exact mappings for high-signal CK skills to avoid falling into "other".
EXACT_CATEGORY_MAP = {
    # Utilities & Helpers
    "ask": "utilities",
    "bootstrap": "utilities",
    "brainstorm": "utilities",
    "ck-autoresearch": "utilities",
    "ck-debug": "utilities",
    "ck-loop": "utilities",
    "ck-predict": "utilities",
    "ck-scenario": "utilities",
    "code-review": "utilities",
    "coding-level": "utilities",
    "context-engineering": "utilities",
    "cook": "utilities",
    "copywriting": "utilities",
    "debug": "utilities",
    "docs": "utilities",
    "fix": "utilities",
    "journal": "utilities",
    "markdown-novel-viewer": "utilities",
    "mermaidjs-v11": "utilities",
    "plan": "utilities",
    "ck-plan": "utilities",
    "preview": "utilities",
    "problem-solving": "utilities",
    "project-management": "utilities",
    "project-organization": "utilities",
    "research": "utilities",
    "retro": "utilities",
    "sequential-thinking": "utilities",
    "test": "utilities",
    "watzup": "utilities",
    # Development Tools
    "find-skills": "dev-tools",
    "git": "dev-tools",
    "gkg": "dev-tools",
    "kanban": "dev-tools",
    "llms": "dev-tools",
    "mintlify": "dev-tools",
    "plans-kanban": "dev-tools",
    "scout": "dev-tools",
    "ship": "dev-tools",
    "team": "dev-tools",
    "use-mcp": "dev-tools",
    "worktree": "dev-tools",
    # Frontend & Design
    "react-best-practices": "frontend",
    "remotion": "frontend",
    "shader": "frontend",
    "stitch": "frontend",
    "web-design-guidelines": "frontend",
    # Frameworks & Platforms
    "tanstack": "frameworks",
    # Infrastructure & DevOps
    "deploy": "infrastructure",
    # Multimedia & Processing
    "agent-browser": "multimedia",
    "web-testing": "multimedia",
    # Security (mapped to utilities)
    "ck-security": "utilities",
    "security-scan": "utilities",
}

def extract_frontmatter(content: str) -> Dict:
    """Extract YAML frontmatter from markdown content."""
    match = re.match(r'^---\s*\n(.*?)\n---\s*\n', content, re.DOTALL)
    if match:
        try:
            return yaml.safe_load(match.group(1))
        except:
            return {}
    return {}

def extract_first_paragraph(content: str) -> str:
    """Extract first meaningful paragraph after frontmatter."""
    # Remove frontmatter
    content = re.sub(r'^---\s*\n.*?\n---\s*\n', '', content, flags=re.DOTALL)

    # Find first paragraph (after headings)
    lines = content.split('\n')
    paragraph = []

    for line in lines:
        line = line.strip()
        # Skip headings and empty lines
        if line.startswith('#') or not line:
            if paragraph:  # If we've started collecting, stop
                break
            continue

        paragraph.append(line)

        # Stop after first paragraph
        if line.endswith('.') and len(' '.join(paragraph)) > 50:
            break

    return ' '.join(paragraph)[:200]

def scan_skills(base_path: Path) -> List[Dict]:
    """Scan all skill files and extract metadata."""
    skills = []

    for skill_file in sorted(base_path.rglob('SKILL.md')):
        # Get skill directory name
        skill_dir = skill_file.parent
        skill_name = skill_dir.name

        # Skip template
        if skill_name == 'template-skill':
            continue

        # Handle nested skills (like document-skills/*)
        if skill_dir.parent.name != 'skills':
            parent_name = skill_dir.parent.name
            skill_name = f"{parent_name}/{skill_name}"

        try:
            content = skill_file.read_text()
            frontmatter = extract_frontmatter(content)

            description = frontmatter.get('description', '')
            if not description:
                description = extract_first_paragraph(content)

            # Categorize based on content/name
            category = categorize_skill(skill_name, description, content)

            skill_entry = {
                'name': skill_name,
                'path': str(skill_file.relative_to(Path('.opencode/skills'))),
                'description': description,
                'category': category,
                'has_scripts': (skill_dir / 'scripts').exists(),
                'has_references': (skill_dir / 'references').exists()
            }

            # Include argument-hint if present in frontmatter
            argument_hint = frontmatter.get('argument-hint', '')
            if argument_hint:
                skill_entry['argument_hint'] = str(argument_hint)

            skills.append(skill_entry)
        except Exception as e:
            print(f"Error processing {skill_file}: {e}")

    return skills

def categorize_skill(name: str, description: str, content: str) -> str:
    """Categorize skill based on name and content."""
    lower_name = name.lower()
    if lower_name in EXACT_CATEGORY_MAP:
        return EXACT_CATEGORY_MAP[lower_name]

    # AI/ML
    if any(x in lower_name for x in ['ai-', 'gemini', 'multimodal', 'adk']):
        return 'ai-ml'

    # Frontend
    if any(x in lower_name for x in ['frontend', 'ui', 'design', 'aesthetic', 'threejs']):
        return 'frontend'

    # Backend
    if any(x in lower_name for x in ['backend', 'auth', 'payment']):
        return 'backend'

    # Infrastructure
    if any(x in lower_name for x in ['devops', 'docker', 'cloudflare', 'gcloud']):
        return 'infrastructure'

    # Database
    if any(x in lower_name for x in ['database', 'mongodb', 'postgresql', 'sql']):
        return 'database'

    # Development Tools
    if any(x in lower_name for x in ['mcp', 'skill-creator', 'repomix', 'docs-seeker']):
        return 'dev-tools'

    # Multimedia
    if any(x in lower_name for x in ['media', 'chrome-devtools', 'document-skills']):
        return 'multimedia'

    # Frameworks
    if any(x in lower_name for x in ['web-frameworks', 'mobile', 'shopify']):
        return 'frameworks'

    # Utilities
    if any(x in lower_name for x in ['debug', 'problem', 'code-review', 'planning', 'research', 'sequential']):
        return 'utilities'

    return 'other'

def group_by_category(skills: List[Dict]) -> Dict[str, List[Dict]]:
    """Group skills by category."""
    categories = {}

    for skill in skills:
        category = skill['category']
        if category not in categories:
            categories[category] = []
        categories[category].append(skill)

    return categories

def main():
    """Main execution."""
    base_path = Path('.opencode/skills')

    if not base_path.exists():
        print(f"Error: {base_path} not found")
        return

    print("Scanning skills...")
    skills = scan_skills(base_path)

    print(f"\nFound {len(skills)} skills\n")

    # Group by category
    categories = group_by_category(skills)

    category_names = {
        'ai-ml': 'AI & Machine Learning',
        'frontend': 'Frontend & Design',
        'backend': 'Backend Development',
        'infrastructure': 'Infrastructure & DevOps',
        'database': 'Database & Storage',
        'dev-tools': 'Development Tools',
        'multimedia': 'Multimedia & Processing',
        'frameworks': 'Frameworks & Platforms',
        'utilities': 'Utilities & Helpers',
        'other': 'Other'
    }

    for category, skills_list in sorted(categories.items()):
        print(f"\n{category_names.get(category, category.upper())}:")
        for skill in skills_list:
            scripts = '📦' if skill['has_scripts'] else '  '
            refs = '📚' if skill['has_references'] else '  '
            print(f"  {scripts}{refs} {skill['name']:30} {skill['description'][:80]}")

    # Output YAML to scripts directory
    output_path = Path('.opencode/scripts/skills_data.yaml')
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_text(yaml.dump(skills, allow_unicode=True, default_flow_style=False))
    print(f"\n✓ Saved metadata to {output_path}")

if __name__ == '__main__':
    main()
