#!/usr/bin/env python3
"""
Tool Auto Loader - Dynamic tool discovery and documentation loading

Features:
1. Auto-discover available tools from config
2. Load tool documentation from docstrings/comments
3. Cache tool info for performance
4. Provide tool recommendations based on task
5. Track tool usage patterns
"""

import json
import re
from pathlib import Path
from typing import Dict, List, Set, Optional, Any
from datetime import datetime
import hashlib

class ToolAutoLoader:
    """Dynamically discovers and loads tool documentation"""

    # Standard Claude Code tools
    STANDARD_TOOLS = {
        "Read": "Read file contents - use for examining code and documentation",
        "Write": "Write or create files - use to create new files or overwrite",
        "Edit": "Edit existing files with line-based replacements",
        "Glob": "Find files matching patterns - use for file discovery",
        "Grep": "Search file contents - use for code search",
        "Bash": "Execute shell commands - use for system operations",
        "Task": "Launch specialized agents - use for complex multi-step tasks",
        "TodoWrite": "Manage task lists and progress tracking",
        "AskUserQuestion": "Ask user for clarification or decisions",
        "WebSearch": "Search the web for current information",
        "WebFetch": "Fetch and analyze web content",
        "Skill": "Execute pre-configured skills",
    }

    # MCP Server tools (shared ecosystem)
    MCP_TOOLS = {
        "zen": "Deep reasoning, code review, debugging via Gemini 3",
        "dev-tools": "Browser debugging, screenshots, console access",
        "task-queue": "Queue and track async tasks",
        "sarlo-admin": "Server administration and configuration",
        "shared-projects-memory": "Shared knowledge graph across projects",
        "backup": "Create and manage backups",
    }

    def __init__(self, cache_dir: Optional[Path] = None):
        """Initialize tool loader

        Args:
            cache_dir: Optional directory for caching tool metadata
        """
        self.cache_dir = cache_dir or Path("/tmp/.luzia-tool-cache")
        self.cache_dir.mkdir(parents=True, exist_ok=True)
        self.tools_cache: Dict[str, Dict] = {}
        self.usage_stats: Dict[str, int] = {}
        self.load_cache()

    def load_cache(self) -> None:
        """Load cached tool metadata from disk"""
        cache_file = self.cache_dir / "tools_cache.json"
        if cache_file.exists():
            try:
                data = json.loads(cache_file.read_text())
                self.tools_cache = data.get("tools", {})
                self.usage_stats = data.get("usage", {})
            except Exception as e:
                print(f"[Warning] Failed to load tool cache: {e}")

    def save_cache(self) -> None:
        """Save tool metadata to cache"""
        cache_file = self.cache_dir / "tools_cache.json"
        cache_file.write_text(json.dumps({
            "tools": self.tools_cache,
            "usage": self.usage_stats,
            "timestamp": datetime.now().isoformat()
        }, indent=2))

    def discover_tools(self, project_config: Dict[str, Any]) -> Dict[str, Dict]:
        """Discover available tools for a project

        Args:
            project_config: Project configuration dict

        Returns:
            Dict of available tools with metadata
        """
        available = {}
        tools_list = project_config.get("tools", [])

        # Add standard tools
        for tool in tools_list:
            if tool in self.STANDARD_TOOLS:
                available[tool] = {
                    "type": "standard",
                    "description": self.STANDARD_TOOLS[tool],
                    "category": self._categorize_tool(tool),
                    "usage_count": self.usage_stats.get(tool, 0)
                }

        # Add MCP tools if available
        shared_tools = project_config.get("shared_tools", {})
        for tool_name, description in shared_tools.items():
            available[tool_name] = {
                "type": "mcp",
                "description": description,
                "category": self._categorize_tool(tool_name),
                "usage_count": self.usage_stats.get(tool_name, 0)
            }

        return available

    def _categorize_tool(self, tool: str) -> str:
        """Categorize a tool by function"""
        categories = {
            # File operations
            "Read": "file_read",
            "Write": "file_write",
            "Edit": "file_edit",
            "Glob": "file_search",
            "Grep": "file_search",

            # System operations
            "Bash": "system",
            "Task": "delegation",

            # Knowledge and reasoning
            "zen": "reasoning",
            "sarlo-admin": "administration",
            "shared-projects-memory": "knowledge",

            # User interaction
            "AskUserQuestion": "interaction",
            "WebSearch": "research",
            "WebFetch": "research",

            # Task management
            "TodoWrite": "planning",
            "task-queue": "async",

            # Execution
            "Skill": "special",
        }
        return categories.get(tool, "other")

    def recommend_tools(self, task: str, available_tools: Dict[str, Dict]) -> List[str]:
        """Recommend tools for a task

        Args:
            task: Task description
            available_tools: Dict of available tools

        Returns:
            Ordered list of recommended tool names
        """
        recommendations = []
        task_lower = task.lower()

        # Keyword-based recommendations
        patterns = {
            # File-based tasks
            r"(read|view|examine|check|look at|find|search|grep)": ["Read", "Glob", "Grep"],
            r"(create|write|generate|output)": ["Write", "Edit"],
            r"(modify|change|update|fix|edit)": ["Edit", "Read"],
            r"(delete|remove|clean)": ["Edit", "Bash"],

            # System tasks
            r"(run|execute|start|stop|restart|service|systemd|docker)": ["Bash"],
            r"(check|verify|status|health)": ["Bash", "Read"],

            # Code/analysis tasks
            r"(analyze|review|understand|debug|error)": ["Read", "Grep", "Bash"],
            r"(test|build|compile|lint)": ["Bash"],

            # Research/learning tasks
            r"(research|search|find|learn|lookup|stack|reference)": ["WebSearch", "WebFetch"],

            # Reasoning tasks
            r"(think|reason|analyze|design|plan)": ["zen"],

            # Project management
            r"(track|todo|progress|schedule)": ["TodoWrite"],

            # Knowledge/memory tasks
            r"(remember|store|document|knowledge)": ["shared-projects-memory"],
        }

        scored_tools = {}
        for pattern, tools in patterns.items():
            if re.search(pattern, task_lower):
                for tool in tools:
                    if tool in available_tools:
                        scored_tools[tool] = scored_tools.get(tool, 0) + 1

        # Sort by score and frequency of use
        recommendations = sorted(
            scored_tools.keys(),
            key=lambda t: (scored_tools[t], self.usage_stats.get(t, 0)),
            reverse=True
        )

        # Add commonly used tools if not already included
        common = ["Read", "Bash", "Edit"]
        for tool in common:
            if tool in available_tools and tool not in recommendations:
                recommendations.append(tool)

        return recommendations[:5]  # Top 5 recommendations

    def record_tool_usage(self, tool: str) -> None:
        """Record that a tool was used

        Args:
            tool: Tool name used
        """
        self.usage_stats[tool] = self.usage_stats.get(tool, 0) + 1

    def get_tool_documentation(self, tool: str) -> Dict[str, Any]:
        """Get detailed documentation for a tool

        Args:
            tool: Tool name

        Returns:
            Dict with tool documentation and usage info
        """
        if tool in self.STANDARD_TOOLS:
            return {
                "name": tool,
                "type": "standard",
                "description": self.STANDARD_TOOLS[tool],
                "usage_count": self.usage_stats.get(tool, 0),
                "url": f"https://docs.anthropic.com/claude-code/{tool.lower()}"
            }

        if tool in self.MCP_TOOLS:
            return {
                "name": tool,
                "type": "mcp",
                "description": self.MCP_TOOLS[tool],
                "usage_count": self.usage_stats.get(tool, 0),
            }

        return {
            "name": tool,
            "type": "unknown",
            "description": "Unknown tool",
            "usage_count": self.usage_stats.get(tool, 0)
        }

    def generate_tool_reference(self, available_tools: List[str]) -> str:
        """Generate a markdown reference for available tools

        Args:
            available_tools: List of available tool names

        Returns:
            Markdown reference text
        """
        sections = ["# Available Tools Reference\n"]

        # Group by category
        by_category = {}
        for tool in available_tools:
            doc = self.get_tool_documentation(tool)
            category = doc.get("type", "other")
            if category not in by_category:
                by_category[category] = []
            by_category[category].append((tool, doc))

        # Write sections
        for category in ["standard", "mcp", "other"]:
            if category in by_category:
                sections.append(f"\n## {category.title()} Tools\n")
                for tool, doc in by_category[category]:
                    sections.append(f"**{tool}**: {doc['description']}")

        return "\n".join(sections)

    def load_project_documentation(self, project_path: Path) -> Dict[str, str]:
        """Load documentation from project files

        Args:
            project_path: Path to project

        Returns:
            Dict of documentation by topic
        """
        docs = {}

        # Look for README, docs, etc
        doc_files = [
            project_path / "README.md",
            project_path / "ARCHITECTURE.md",
            project_path / ".claude.md",
            project_path / "docs" / "index.md",
        ]

        for doc_file in doc_files:
            if doc_file.exists():
                try:
                    content = doc_file.read_text()
                    # Extract first 500 chars as summary
                    docs[doc_file.stem] = content[:500]
                except Exception as e:
                    pass

        return docs

    def get_tools_by_category(self, available_tools: Dict[str, Dict]) -> Dict[str, List[str]]:
        """Group tools by category

        Args:
            available_tools: Dict of available tools

        Returns:
            Dict with category -> list of tool names
        """
        by_category = {}
        for tool_name, tool_info in available_tools.items():
            category = tool_info.get("category", "other")
            if category not in by_category:
                by_category[category] = []
            by_category[category].append(tool_name)

        return by_category

    def get_top_tools(self, available_tools: Dict[str, Dict], limit: int = 5) -> List[str]:
        """Get most frequently used tools

        Args:
            available_tools: Dict of available tools
            limit: Max tools to return

        Returns:
            List of most-used tool names
        """
        return sorted(
            available_tools.keys(),
            key=lambda t: self.usage_stats.get(t, 0),
            reverse=True
        )[:limit]
