"""
System Service Module

Provides system monitoring and health check functionality for the Remote Access API.
Includes checks for database connectivity, daemon status, and system resources.
"""

import socket
import psutil
from datetime import datetime
from typing import Dict, Any, Optional
import structlog

logger = structlog.get_logger(__name__)


class SystemService:
    """Service for system health checks and monitoring"""

    def __init__(self, service_start_time: Optional[datetime] = None):
        """
        Initialize SystemService
        
        Args:
            service_start_time: Service startup time for uptime calculation
        """
        self.service_start_time = service_start_time or datetime.now()

    @staticmethod
    def check_database_connection(guacamole_client: Any, guacamole_url: str) -> Dict[str, Any]:
        """
        Check Guacamole database connectivity
        
        Args:
            guacamole_client: Guacamole client instance
            guacamole_url: Guacamole base URL
            
        Returns:
            Status dictionary with connection state
        """
        try:
            # Try to get system token (requires database access)
            token = guacamole_client.get_system_token()
            
            if token:
                return {
                    "status": "ok",
                    "message": "Database connection healthy"
                }
            else:
                return {
                    "status": "error",
                    "message": "Failed to obtain system token"
                }
                
        except Exception as e:
            logger.error("Database connection check failed", error=str(e))
            return {
                "status": "error",
                "error": str(e),
                "message": "Database connection failed"
            }

    @staticmethod
    def check_guacd_daemon() -> Dict[str, Any]:
        """
        Check if guacd daemon is running
        
        Returns:
            Status dictionary with daemon state
        """
        try:
            # Check if guacd is listening on default port 4822
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(2)
            result = sock.connect_ex(('localhost', 4822))
            sock.close()
            
            if result == 0:
                return {
                    "status": "ok",
                    "message": "guacd daemon is running",
                    "port": 4822
                }
            else:
                return {
                    "status": "error",
                    "message": "guacd daemon is not accessible",
                    "port": 4822
                }
                
        except Exception as e:
            logger.error("guacd daemon check failed", error=str(e))
            return {
                "status": "error",
                "error": str(e),
                "message": "Failed to check guacd daemon"
            }

    @staticmethod
    def check_system_resources() -> Dict[str, Any]:
        """
        Check system resources (CPU, RAM, Disk)
        
        Returns:
            Status dictionary with resource usage
        """
        try:
            # CPU usage
            cpu_percent = psutil.cpu_percent(interval=1)
            
            # Memory usage
            memory = psutil.virtual_memory()
            memory_percent = memory.percent
            
            # Disk usage
            disk = psutil.disk_usage('/')
            disk_percent = disk.percent
            
            # Determine overall status based on thresholds
            status = "ok"
            warnings = []
            
            if cpu_percent > 90:
                status = "critical"
                warnings.append(f"CPU usage critical: {cpu_percent}%")
            elif cpu_percent > 80:
                status = "warning"
                warnings.append(f"CPU usage high: {cpu_percent}%")
            
            if memory_percent > 90:
                status = "critical"
                warnings.append(f"Memory usage critical: {memory_percent}%")
            elif memory_percent > 80:
                if status == "ok":
                    status = "warning"
                warnings.append(f"Memory usage high: {memory_percent}%")
            
            if disk_percent > 90:
                status = "critical"
                warnings.append(f"Disk usage critical: {disk_percent}%")
            elif disk_percent > 80:
                if status == "ok":
                    status = "warning"
                warnings.append(f"Disk usage high: {disk_percent}%")
            
            result = {
                "status": status,
                "cpu_percent": round(cpu_percent, 2),
                "memory_percent": round(memory_percent, 2),
                "disk_percent": round(disk_percent, 2),
                "memory_available_gb": round(memory.available / (1024**3), 2),
                "disk_free_gb": round(disk.free / (1024**3), 2)
            }
            
            if warnings:
                result["warnings"] = warnings
            
            if status == "ok":
                result["message"] = "System resources healthy"
            
            return result
            
        except Exception as e:
            logger.error("System resources check failed", error=str(e))
            return {
                "status": "error",
                "error": str(e),
                "message": "Failed to check system resources"
            }

    def get_system_info(self) -> Dict[str, Any]:
        """
        Get system information (uptime, version, etc.)
        
        Returns:
            Dictionary with system information
        """
        try:
            uptime_seconds = int((datetime.now() - self.service_start_time).total_seconds())
            
            return {
                "uptime_seconds": uptime_seconds,
                "uptime_formatted": self._format_uptime(uptime_seconds),
                "python_version": f"{psutil.PROCFS_PATH if hasattr(psutil, 'PROCFS_PATH') else 'N/A'}",
                "cpu_count": psutil.cpu_count(),
                "boot_time": datetime.fromtimestamp(psutil.boot_time()).isoformat()
            }
            
        except Exception as e:
            logger.error("Failed to get system info", error=str(e))
            return {
                "error": str(e),
                "message": "Failed to retrieve system information"
            }

    @staticmethod
    def _format_uptime(seconds: int) -> str:
        """
        Format uptime seconds to human-readable string
        
        Args:
            seconds: Uptime in seconds
            
        Returns:
            Formatted uptime string
        """
        days = seconds // 86400
        hours = (seconds % 86400) // 3600
        minutes = (seconds % 3600) // 60
        secs = seconds % 60
        
        parts = []
        if days > 0:
            parts.append(f"{days}d")
        if hours > 0:
            parts.append(f"{hours}h")
        if minutes > 0:
            parts.append(f"{minutes}m")
        if secs > 0 or not parts:
            parts.append(f"{secs}s")
        
        return " ".join(parts)


