#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
# See LICENSE file for details.
"""
Tool Registry Generator: Auto-inventory of all PULSE tools.

Scans pulse/brain/*.py, extracts docstrings,
categorizes by purpose, and generates REGISTRY.md.

Usage:
    python generate_registry.py              # Generate REGISTRY.md
    python generate_registry.py --json       # Output as JSON

Dependencies: Python stdlib only (Law 4)
"""

import ast
import json
import sys
from datetime import datetime, timezone
from pathlib import Path

SCRIPT_DIR = Path(__file__).resolve().parent
ROOT_DIR = SCRIPT_DIR.parent.parent.parent
REGISTRY_FILE = SCRIPT_DIR / "REGISTRY.md"

# Tool categories based on naming and purpose
_CATEGORIES = {
    "Brain Operations": ["brain_query", "brain_search", "brain_recommender",
                         "brain_validators", "brain_utils"],
    "Knowledge Pipeline": ["knowledge_extractor", "auto_capture",
                           "anti_pattern_builder", "wants_parser",
                           "private_synthesis", "synthesize_plans"],
    "Task Management": ["pulse_boot", "pulse_save", "pulse_relay",
                        "pulse_scaffold", "pulse_prune"],
    "Monitoring & Metrics": ["growth_monitor", "performance_profiler",
                             "agent_logs_aggregator", "skill_effectiveness",
                             "tool_dependency_graph"],
    "Configuration": ["config_manager", "pulse_crypto"],
    "Search & Recommendation": ["skill_recommender", "conflict_resolver"],
}


def _extract_tool_info(py_file: Path) -> dict:
    """Extract tool metadata from a Python file."""
    info = {
        "name": py_file.stem,
        "file": py_file.name,
        "purpose": "",
        "has_cli": False,
        "functions": [],
        "imports": [],
        "lines": 0,
    }

    try:
        source = py_file.read_text(encoding="utf-8", errors="replace")
        info["lines"] = len(source.splitlines())

        tree = ast.parse(source)

        # Extract module docstring
        docstring = ast.get_docstring(tree) or ""
        # Get first non-empty line after the title
        for line in docstring.split("\n"):
            line = line.strip()
            if line and not line.startswith(("Copyright", "See LICENSE", "---")):
                # Skip the module name line
                if ":" in line and len(line) < 100:
                    info["purpose"] = line.split(":", 1)[1].strip()
                    break
                elif len(line) > 10:
                    info["purpose"] = line[:100]
                    break

        # Check for __main__ block
        for node in ast.walk(tree):
            if isinstance(node, ast.If):
                try:
                    test = node.test
                    if (isinstance(test, ast.Compare) and
                        isinstance(test.left, ast.Name) and
                        test.left.id == "__name__"):
                        info["has_cli"] = True
                except (AttributeError, TypeError):
                    pass

        # Extract top-level function names
        for node in ast.iter_child_nodes(tree):
            if isinstance(node, ast.FunctionDef):
                if not node.name.startswith("_"):
                    info["functions"].append(node.name)
            elif isinstance(node, ast.ClassDef):
                info["functions"].append(f"{node.name} (class)")

    except (SyntaxError, Exception) as e:
        info["purpose"] = f"Parse error: {e}"

    return info


def _categorize(tool_name: str) -> str:
    """Find the category for a tool."""
    for category, tools in _CATEGORIES.items():
        if tool_name in tools:
            return category
    return "Other"


def generate_registry() -> dict:
    """Scan all tools and generate registry data."""
    tools = []
    for py_file in sorted(SCRIPT_DIR.glob("*.py")):
        if py_file.name.startswith("__"):
            continue
        info = _extract_tool_info(py_file)
        info["category"] = _categorize(info["name"])
        tools.append(info)

    return {
        "generated": datetime.now(timezone.utc).isoformat(),
        "total_tools": len(tools),
        "tools": tools,
    }


def write_registry_md(data: dict) -> None:
    """Write REGISTRY.md from registry data."""
    lines = [
        "# PULSE Tools Registry",
        f"> Auto-generated: {data['generated'][:10]}",
        f"> Total: {data['total_tools']} tools",
        "",
        "---",
        "",
    ]

    # Group by category
    categories = {}
    for tool in data["tools"]:
        cat = tool["category"]
        categories.setdefault(cat, []).append(tool)

    for cat in sorted(categories.keys()):
        tools = categories[cat]
        lines.append(f"## {cat} ({len(tools)} tools)")
        lines.append("")
        lines.append("| Tool | Purpose | CLI | Lines | Key Functions |")
        lines.append("|------|---------|-----|-------|---------------|")
        for t in sorted(tools, key=lambda x: x["name"]):
            cli = "Yes" if t["has_cli"] else "-"
            funcs = ", ".join(t["functions"][:3])
            if len(t["functions"]) > 3:
                funcs += f" (+{len(t['functions'])-3})"
            purpose = t["purpose"][:60] or "No docstring"
            lines.append(f"| {t['file']} | {purpose} | {cli} | {t['lines']} | {funcs} |")
        lines.append("")

    # Quick reference
    lines.append("## Quick Reference")
    lines.append("")
    lines.append("**New to PULSE?** Start with:")
    lines.append("- `brain_query.py --query \"<task>\"` — Search brain before acting")
    lines.append("- `pulse_boot.py` — Agent bootstrap")
    lines.append("- `pulse_save.py --agent <name> --learnings \"...\"` — Save learnings")
    lines.append("")
    lines.append("**Task dispatch:** `pulse_relay.py --tasks \"Title:domain:tier\"`")
    lines.append("")
    lines.append("**Health check:** `growth_monitor.py`")
    lines.append("")

    REGISTRY_FILE.write_text("\n".join(lines), encoding="utf-8")
    return len(data["tools"])


if __name__ == "__main__":
    data = generate_registry()

    if "--json" in sys.argv:
        print(json.dumps(data, indent=2))
    else:
        count = write_registry_md(data)
        print(f"[REGISTRY] Generated REGISTRY.md with {count} tools")
