"""
System Tools for Uni-Wizard
Monitor and control the VPS environment
"""

import os
import json
import subprocess
import platform
import psutil
from datetime import datetime, timedelta
from typing import Dict, List, Optional

from .registry import tool, registry


@tool(category="system")
def system_info() -> str:
    """
    Get comprehensive system information.
    
    Returns:
        JSON string with OS, CPU, memory, disk, and uptime info
    """
    try:
        # CPU info
        cpu_count = psutil.cpu_count()
        cpu_percent = psutil.cpu_percent(interval=1)
        cpu_freq = psutil.cpu_freq()
        
        # Memory info
        memory = psutil.virtual_memory()
        
        # Disk info
        disk = psutil.disk_usage('/')
        
        # Uptime
        boot_time = datetime.fromtimestamp(psutil.boot_time())
        uptime = datetime.now() - boot_time
        
        # Load average (Linux only)
        load_avg = os.getloadavg() if hasattr(os, 'getloadavg') else [0, 0, 0]
        
        info = {
            "hostname": platform.node(),
            "os": {
                "system": platform.system(),
                "release": platform.release(),
                "version": platform.version(),
                "machine": platform.machine()
            },
            "cpu": {
                "count": cpu_count,
                "percent": cpu_percent,
                "frequency_mhz": cpu_freq.current if cpu_freq else None
            },
            "memory": {
                "total_gb": round(memory.total / (1024**3), 2),
                "available_gb": round(memory.available / (1024**3), 2),
                "percent_used": memory.percent
            },
            "disk": {
                "total_gb": round(disk.total / (1024**3), 2),
                "free_gb": round(disk.free / (1024**3), 2),
                "percent_used": round((disk.used / disk.total) * 100, 1)
            },
            "uptime": {
                "boot_time": boot_time.isoformat(),
                "uptime_seconds": int(uptime.total_seconds()),
                "uptime_human": str(timedelta(seconds=int(uptime.total_seconds())))
            },
            "load_average": {
                "1min": round(load_avg[0], 2),
                "5min": round(load_avg[1], 2),
                "15min": round(load_avg[2], 2)
            }
        }
        
        return json.dumps(info, indent=2)
        
    except Exception as e:
        return f"Error getting system info: {str(e)}"


@tool(category="system")
def process_list(filter_name: str = None) -> str:
    """
    List running processes with optional name filter.
    
    Args:
        filter_name: Optional process name to filter by
        
    Returns:
        JSON list of processes with PID, name, CPU%, memory
    """
    try:
        processes = []
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent', 'status']):
            try:
                info = proc.info
                if filter_name and filter_name.lower() not in info['name'].lower():
                    continue
                processes.append({
                    "pid": info['pid'],
                    "name": info['name'],
                    "cpu_percent": info['cpu_percent'],
                    "memory_percent": round(info['memory_percent'], 2) if info['memory_percent'] else 0,
                    "status": info['status']
                })
            except (psutil.NoSuchProcess, psutil.AccessDenied):
                continue
        
        # Sort by CPU usage
        processes.sort(key=lambda x: x['cpu_percent'], reverse=True)
        
        return json.dumps({
            "count": len(processes),
            "filter": filter_name,
            "processes": processes[:50]  # Limit to top 50
        }, indent=2)
        
    except Exception as e:
        return f"Error listing processes: {str(e)}"


@tool(category="system")
def service_status(service_name: str) -> str:
    """
    Check systemd service status.
    
    Args:
        service_name: Name of the service (e.g., 'llama-server', 'syncthing@root')
        
    Returns:
        Service status information
    """
    try:
        result = subprocess.run(
            ['systemctl', 'status', service_name, '--no-pager'],
            capture_output=True,
            text=True
        )
        
        # Parse output
        lines = result.stdout.split('\n')
        status_info = {"service": service_name}
        
        for line in lines:
            if 'Active:' in line:
                status_info['active'] = line.split(':', 1)[1].strip()
            elif 'Loaded:' in line:
                status_info['loaded'] = line.split(':', 1)[1].strip()
            elif 'Main PID:' in line:
                status_info['pid'] = line.split(':', 1)[1].strip()
            elif 'Memory:' in line:
                status_info['memory'] = line.split(':', 1)[1].strip()
            elif 'CPU:' in line:
                status_info['cpu'] = line.split(':', 1)[1].strip()
        
        status_info['exit_code'] = result.returncode
        
        return json.dumps(status_info, indent=2)
        
    except Exception as e:
        return f"Error checking service status: {str(e)}"


@tool(category="system")
def service_control(service_name: str, action: str) -> str:
    """
    Control a systemd service (start, stop, restart, enable, disable).
    
    Args:
        service_name: Name of the service
        action: start, stop, restart, enable, disable, status
        
    Returns:
        Result of the action
    """
    valid_actions = ['start', 'stop', 'restart', 'enable', 'disable', 'status']
    
    if action not in valid_actions:
        return f"Invalid action. Use: {', '.join(valid_actions)}"
    
    try:
        result = subprocess.run(
            ['systemctl', action, service_name],
            capture_output=True,
            text=True
        )
        
        if result.returncode == 0:
            return f"✓ Service '{service_name}' {action} successful"
        else:
            return f"✗ Service '{service_name}' {action} failed: {result.stderr}"
            
    except Exception as e:
        return f"Error controlling service: {str(e)}"


@tool(category="system")
def health_check() -> str:
    """
    Comprehensive health check of the VPS.
    
    Checks:
    - System resources (CPU, memory, disk)
    - Critical services (llama-server, syncthing, timmy-agent)
    - Network connectivity
    - Inference endpoint
    
    Returns:
        Health report with status and recommendations
    """
    try:
        health = {
            "timestamp": datetime.now().isoformat(),
            "overall": "healthy",
            "checks": {}
        }
        
        # System resources
        memory = psutil.virtual_memory()
        disk = psutil.disk_usage('/')
        
        health["checks"]["memory"] = {
            "status": "healthy" if memory.percent < 90 else "warning",
            "percent_used": memory.percent,
            "available_gb": round(memory.available / (1024**3), 2)
        }
        
        health["checks"]["disk"] = {
            "status": "healthy" if disk.percent < 90 else "warning",
            "percent_used": disk.percent,
            "free_gb": round(disk.free / (1024**3), 2)
        }
        
        # Check inference endpoint
        try:
            import urllib.request
            req = urllib.request.urlopen('http://127.0.0.1:8081/health', timeout=5)
            health["checks"]["inference"] = {"status": "healthy", "port": 8081}
        except:
            health["checks"]["inference"] = {"status": "down", "port": 8081}
            health["overall"] = "degraded"
        
        # Check services
        services = ['llama-server', 'syncthing@root']
        for svc in services:
            result = subprocess.run(['systemctl', 'is-active', svc], capture_output=True, text=True)
            health["checks"][svc] = {
                "status": "healthy" if result.returncode == 0 else "down"
            }
            if result.returncode != 0:
                health["overall"] = "degraded"
        
        return json.dumps(health, indent=2)
        
    except Exception as e:
        return f"Error running health check: {str(e)}"


@tool(category="system")
def disk_usage(path: str = "/") -> str:
    """
    Get disk usage for a path.
    
    Args:
        path: Path to check (default: /)
        
    Returns:
        Disk usage statistics
    """
    try:
        usage = psutil.disk_usage(path)
        return json.dumps({
            "path": path,
            "total_gb": round(usage.total / (1024**3), 2),
            "used_gb": round(usage.used / (1024**3), 2),
            "free_gb": round(usage.free / (1024**3), 2),
            "percent_used": round((usage.used / usage.total) * 100, 1)
        }, indent=2)
    except Exception as e:
        return f"Error checking disk usage: {str(e)}"


# Auto-register all tools in this module
def register_all():
    """Register all system tools"""
    registry.register(
        name="system_info",
        handler=system_info,
        description="Get comprehensive system information (OS, CPU, memory, disk, uptime)",
        category="system"
    )
    
    registry.register(
        name="process_list",
        handler=process_list,
        description="List running processes with optional name filter",
        parameters={
            "type": "object",
            "properties": {
                "filter_name": {
                    "type": "string",
                    "description": "Optional process name to filter by"
                }
            }
        },
        category="system"
    )
    
    registry.register(
        name="service_status",
        handler=service_status,
        description="Check systemd service status",
        parameters={
            "type": "object",
            "properties": {
                "service_name": {
                    "type": "string",
                    "description": "Name of the systemd service"
                }
            },
            "required": ["service_name"]
        },
        category="system"
    )
    
    registry.register(
        name="service_control",
        handler=service_control,
        description="Control a systemd service (start, stop, restart, enable, disable)",
        parameters={
            "type": "object",
            "properties": {
                "service_name": {
                    "type": "string",
                    "description": "Name of the service"
                },
                "action": {
                    "type": "string",
                    "enum": ["start", "stop", "restart", "enable", "disable", "status"],
                    "description": "Action to perform"
                }
            },
            "required": ["service_name", "action"]
        },
        category="system"
    )
    
    registry.register(
        name="health_check",
        handler=health_check,
        description="Comprehensive health check of VPS (resources, services, inference)",
        category="system"
    )
    
    registry.register(
        name="disk_usage",
        handler=disk_usage,
        description="Get disk usage for a path",
        parameters={
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "Path to check",
                    "default": "/"
                }
            }
        },
        category="system"
    )


register_all()
