"""Comprehensive system and MCP statistics."""

from typing import Unpack, TypedDict, final, override
from pathlib import Path
from datetime import datetime

import psutil
from mcp.server.fastmcp import Context as MCPContext
from hanzo_tools.shell.run_background import RunBackgroundTool
from hanzo_tools.database.database_manager import DatabaseManager

from hanzo_mcp.tools.common.base import BaseTool
from hanzo_mcp.tools.mcp.mcp_add import McpAddTool
from hanzo_mcp.tools.common.context import create_tool_context
from hanzo_mcp.tools.common.auto_timeout import auto_timeout


class StatsParams(TypedDict, total=False):
    """Parameters for stats tool."""

    pass


@final
class StatsTool(BaseTool):
    """Tool for showing comprehensive system and MCP statistics."""

    def __init__(self, db_manager: DatabaseManager = None):
        """Initialize the stats tool.

        Args:
            db_manager: Optional database manager for DB stats
        """
        self.db_manager = db_manager

    @property
    @override
    def name(self) -> str:
        """Get the tool name."""
        return "stats"

    @property
    @override
    def description(self) -> str:
        """Get the tool description."""
        return """Show comprehensive system and Hanzo AI statistics.

Displays:
- System resources (CPU, memory, disk)
- Running processes
- Database usage
- MCP server status
- Tool usage statistics
- Warnings for high resource usage

Example:
- stats
"""

    @override
    @auto_timeout("stats")
    async def call(
        self,
        ctx: MCPContext,
        **params: Unpack[StatsParams],
    ) -> str:
        """Get comprehensive statistics.

        Args:
            ctx: MCP context
            **params: Tool parameters

        Returns:
            Comprehensive statistics
        """
        tool_ctx = create_tool_context(ctx)
        await tool_ctx.set_tool_info(self.name)

        output = []
        warnings = []

        # Header
        output.append("=== Hanzo AI System Statistics ===")
        output.append(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        output.append("")

        # System Resources
        output.append("=== System Resources ===")

        # CPU
        cpu_percent = psutil.cpu_percent(interval=1)
        cpu_count = psutil.cpu_count()
        output.append(f"CPU Usage: {cpu_percent}% ({cpu_count} cores)")
        if cpu_percent > 90:
            warnings.append(f"⚠️  HIGH CPU USAGE: {cpu_percent}%")

        # Memory
        memory = psutil.virtual_memory()
        memory_used_gb = memory.used / (1024**3)
        memory_total_gb = memory.total / (1024**3)
        memory_percent = memory.percent
        output.append(f"Memory: {memory_used_gb:.1f}/{memory_total_gb:.1f} GB ({memory_percent}%)")
        if memory_percent > 90:
            warnings.append(f"⚠️  HIGH MEMORY USAGE: {memory_percent}%")

        # Disk
        disk = psutil.disk_usage("/")
        disk_used_gb = disk.used / (1024**3)
        disk_total_gb = disk.total / (1024**3)
        disk_percent = disk.percent
        disk_free_gb = disk.free / (1024**3)
        output.append(f"Disk: {disk_used_gb:.1f}/{disk_total_gb:.1f} GB ({disk_percent}%)")
        output.append(f"Free Space: {disk_free_gb:.1f} GB")
        if disk_percent > 90:
            warnings.append(f"⚠️  LOW DISK SPACE: Only {disk_free_gb:.1f} GB free ({100 - disk_percent:.1f}% remaining)")

        output.append("")

        # Background Processes
        output.append("=== Background Processes ===")
        processes = RunBackgroundTool.get_processes()
        running_count = 0
        total_memory_mb = 0

        if processes:
            for proc in processes.values():
                if proc.is_running():
                    running_count += 1
                    try:
                        ps_proc = psutil.Process(proc.process.pid)
                        memory_mb = ps_proc.memory_info().rss / (1024**2)
                        total_memory_mb += memory_mb
                    except Exception:
                        pass

            output.append(f"Running Processes: {running_count}")
            output.append(f"Total Memory Usage: {total_memory_mb:.1f} MB")

            # List top processes by memory
            if running_count > 0:
                output.append("\nTop Processes:")
                proc_list = []
                for proc_id, proc in processes.items():
                    if proc.is_running():
                        try:
                            ps_proc = psutil.Process(proc.process.pid)
                            memory_mb = ps_proc.memory_info().rss / (1024**2)
                            cpu = ps_proc.cpu_percent(interval=0.1)
                            proc_list.append((proc.name, memory_mb, cpu, proc_id))
                        except Exception:
                            proc_list.append((proc.name, 0, 0, proc_id))

                proc_list.sort(key=lambda x: x[1], reverse=True)
                for name, mem, cpu, pid in proc_list[:5]:
                    output.append(f"  - {name} ({pid}): {mem:.1f} MB, {cpu:.1f}% CPU")
        else:
            output.append("No background processes running")

        output.append("")

        # Database Usage
        if self.db_manager:
            output.append("=== Database Usage ===")
            db_dir = Path.home() / ".hanzo" / "db"
            total_db_size = 0

            if db_dir.exists():
                for db_file in db_dir.rglob("*.db"):
                    size = db_file.stat().st_size
                    total_db_size += size

                output.append(f"Total Database Size: {total_db_size / (1024**2):.1f} MB")
                output.append(f"Active Projects: {len(self.db_manager.projects)}")

                # List largest databases
                db_sizes = []
                for db_file in db_dir.rglob("*.db"):
                    size = db_file.stat().st_size / (1024**2)
                    if size > 0.1:  # Only show DBs > 100KB
                        project = db_file.parent.parent.name
                        db_type = db_file.stem
                        db_sizes.append((project, db_type, size))

                if db_sizes:
                    db_sizes.sort(key=lambda x: x[2], reverse=True)
                    output.append("\nLargest Databases:")
                    for project, db_type, size in db_sizes[:5]:
                        output.append(f"  - {project}/{db_type}: {size:.1f} MB")
            else:
                output.append("No databases found")

        output.append("")

        # MCP Servers
        output.append("=== MCP Servers ===")
        mcp_servers = McpAddTool.get_servers()
        if mcp_servers:
            running_mcp = sum(1 for s in mcp_servers.values() if s.get("status") == "running")
            total_mcp_tools = sum(len(s.get("tools", [])) for s in mcp_servers.values())

            output.append(f"Total Servers: {len(mcp_servers)}")
            output.append(f"Running: {running_mcp}")
            output.append(f"Total Tools Available: {total_mcp_tools}")
        else:
            output.append("No MCP servers configured")

        output.append("")

        # Hanzo AI Specifics
        output.append("=== Hanzo AI ===")

        # Log directory size
        log_dir = Path.home() / ".hanzo" / "logs"
        if log_dir.exists():
            log_size = sum(f.stat().st_size for f in log_dir.rglob("*") if f.is_file())
            log_count = len(list(log_dir.rglob("*.log")))
            output.append(f"Log Files: {log_count} ({log_size / (1024**2):.1f} MB)")

            if log_size > 100 * 1024**2:  # > 100MB
                warnings.append(f"⚠️  Large log directory: {log_size / (1024**2):.1f} MB")

        # Config directory
        config_dir = Path.home() / ".hanzo" / "mcp"
        if config_dir.exists():
            config_count = len(list(config_dir.rglob("*.json")))
            output.append(f"Config Files: {config_count}")

        # Tool status (if available)
        # Note: Tool usage statistics tracking can be added here
        output.append("\nTool Categories:")
        output.append("  - File Operations: grep, find_files, read, write, edit")
        output.append("  - Shell: bash, run_background, processes, pkill")
        output.append("  - Database: sql_query, graph_query, vector_search")
        output.append("  - Package Runners: uvx, npx, uvx_background, npx_background")
        output.append("  - MCP Management: mcp_add, mcp_remove, mcp_stats")

        # Warnings Section
        if warnings:
            output.append("\n=== ⚠️  WARNINGS ===")
            for warning in warnings:
                output.append(warning)
            output.append("")

        # Recommendations
        output.append("=== Recommendations ===")
        if disk_free_gb < 5:
            output.append("- Free up disk space (< 5GB remaining)")
        if memory_percent > 80:
            output.append("- Close unused applications to free memory")
        if running_count > 10:
            output.append("- Consider stopping unused background processes")
        if log_size > 50 * 1024**2:
            output.append("- Clean up old log files in ~/.hanzo/logs")

        if not any(
            [
                disk_free_gb < 5,
                memory_percent > 80,
                running_count > 10,
                log_size > 50 * 1024**2,
            ]
        ):
            output.append("✅ System resources are healthy")

        return "\n".join(output)

    def register(self, mcp_server) -> None:
        """Register this tool with the MCP server."""
        pass
