"""
Gestionnaire des services systemd pour Skull Pi.
Contrôle start/stop/restart des services via systemctl.
"""

import asyncio
import logging
import subprocess
from typing import Dict, List, Optional


class ServiceManager:
    """Gestionnaire des services Skull Pi."""

    def __init__(self):
        self.logger = logging.getLogger("orchestrator.services")

        # Services gérés par l'orchestrateur
        self.managed_services = {
            "skull-motion": "Service de contrôle moteurs",
            "skull-vision": "Service de vision et détection",
            "skull-voice": "Service de synthèse vocale",
            "skull-audioin": "Service d'acquisition audio",
            "skull-asr": "Service de reconnaissance vocale",
            "skull-ai": "Service d'intelligence artificielle",
        }

        # Cache des statuts
        self._status_cache: Dict[str, Dict] = {}

    async def start_service(self, service_name: str) -> bool:
        """Démarre un service."""
        if service_name not in self.managed_services:
            self.logger.error(f"Service inconnu: {service_name}")
            return False

        try:
            self.logger.info(f"Démarrage du service {service_name}")

            result = await self._run_systemctl("start", service_name)

            if result.returncode == 0:
                self.logger.info(f"Service {service_name} démarré")
                return True
            else:
                self.logger.error(f"Échec démarrage {service_name}: {result.stderr}")
                return False

        except Exception as e:
            self.logger.error(f"Erreur démarrage {service_name}: {e}")
            return False

    async def stop_service(self, service_name: str) -> bool:
        """Arrête un service."""
        if service_name not in self.managed_services:
            self.logger.error(f"Service inconnu: {service_name}")
            return False

        try:
            self.logger.info(f"Arrêt du service {service_name}")

            result = await self._run_systemctl("stop", service_name)

            if result.returncode == 0:
                self.logger.info(f"Service {service_name} arrêté")
                return True
            else:
                self.logger.error(f"Échec arrêt {service_name}: {result.stderr}")
                return False

        except Exception as e:
            self.logger.error(f"Erreur arrêt {service_name}: {e}")
            return False

    async def restart_service(self, service_name: str) -> bool:
        """Redémarre un service."""
        if service_name not in self.managed_services:
            self.logger.error(f"Service inconnu: {service_name}")
            return False

        try:
            self.logger.info(f"Redémarrage du service {service_name}")

            result = await self._run_systemctl("restart", service_name)

            if result.returncode == 0:
                self.logger.info(f"Service {service_name} redémarré")
                return True
            else:
                self.logger.error(f"Échec redémarrage {service_name}: {result.stderr}")
                return False

        except Exception as e:
            self.logger.error(f"Erreur redémarrage {service_name}: {e}")
            return False

    async def get_service_status(self, service_name: str) -> Dict:
        """Récupère le statut d'un service."""
        if service_name not in self.managed_services:
            return {"error": "Service inconnu"}

        try:
            # Statut général
            result = await self._run_systemctl("is-active", service_name)
            active = result.stdout.strip() == "active"

            # Informations détaillées
            result_status = await self._run_systemctl("status", service_name)

            status = {
                "name": service_name,
                "description": self.managed_services[service_name],
                "active": active,
                "status": result.stdout.strip(),
                "enabled": await self._is_service_enabled(service_name),
                "last_check": asyncio.get_event_loop().time(),
            }

            # Parser les infos du status
            if result_status.returncode == 0:
                lines = result_status.stdout.split("\n")
                for line in lines:
                    if "Main PID:" in line:
                        try:
                            pid = line.split("Main PID:")[1].strip().split()[0]
                            status["pid"] = int(pid) if pid.isdigit() else None
                        except:
                            status["pid"] = None
                    elif "Active:" in line:
                        status["detailed_status"] = line.strip()

            self._status_cache[service_name] = status
            return status

        except Exception as e:
            self.logger.error(f"Erreur récupération statut {service_name}: {e}")
            return {"error": str(e), "active": False}

    async def _is_service_enabled(self, service_name: str) -> bool:
        """Vérifie si un service est activé au démarrage."""
        try:
            result = await self._run_systemctl("is-enabled", service_name)
            return result.stdout.strip() == "enabled"
        except:
            return False

    def is_service_running(self, service_name: str) -> bool:
        """Vérifie rapidement si un service tourne (cache)."""
        if service_name in self._status_cache:
            return self._status_cache[service_name].get("active", False)
        return False

    async def get_all_services_status(self) -> Dict[str, Dict]:
        """Récupère le statut de tous les services gérés."""
        status = {}
        for service_name in self.managed_services:
            status[service_name] = await self.get_service_status(service_name)
        return status

    async def start_all_services(self) -> Dict[str, bool]:
        """Démarre tous les services."""
        results = {}
        for service_name in self.managed_services:
            results[service_name] = await self.start_service(service_name)
        return results

    async def stop_all_services(self) -> Dict[str, bool]:
        """Arrête tous les services."""
        results = {}
        for service_name in self.managed_services:
            results[service_name] = await self.stop_service(service_name)
        return results

    async def _run_systemctl(
        self, command: str, service_name: str
    ) -> subprocess.CompletedProcess:
        """Exécute une commande systemctl."""
        cmd = ["sudo", "systemctl", command, service_name]

        process = await asyncio.create_subprocess_exec(
            *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
        )

        stdout, stderr = await process.communicate()

        return subprocess.CompletedProcess(
            args=cmd,
            returncode=process.returncode,
            stdout=stdout.decode("utf-8"),
            stderr=stderr.decode("utf-8"),
        )

    def get_managed_services(self) -> List[str]:
        """Retourne la liste des services gérés."""
        return list(self.managed_services.keys())

    async def enable_service(self, service_name: str) -> bool:
        """Active un service au démarrage."""
        if service_name not in self.managed_services:
            return False

        try:
            result = await self._run_systemctl("enable", service_name)
            return result.returncode == 0
        except Exception as e:
            self.logger.error(f"Erreur activation {service_name}: {e}")
            return False

    async def disable_service(self, service_name: str) -> bool:
        """Désactive un service au démarrage."""
        if service_name not in self.managed_services:
            return False

        try:
            result = await self._run_systemctl("disable", service_name)
            return result.returncode == 0
        except Exception as e:
            self.logger.error(f"Erreur désactivation {service_name}: {e}")
            return False
