# retoor <retoor@molodetz.nl>

import asyncio
import logging

from devplacepy.database import get_setting, set_setting

logger = logging.getLogger(__name__)


class ServiceManager:
    def __init__(self):
        self._services = {}
        self._owns_lock = False

    def set_lock_owner(self, owns: bool) -> None:
        self._owns_lock = owns

    def owns_lock(self) -> bool:
        return self._owns_lock

    def register(self, service) -> None:
        self._services[service.name] = service
        logger.info(f"Registered service: {service.name}")

    def get_service(self, name: str):
        return self._services.get(name)

    def describe_all(self) -> list[dict]:
        return [svc.describe() for svc in self._services.values()]

    def set_enabled(self, name: str, enabled: bool) -> bool:
        svc = self.get_service(name)
        if svc is None:
            return False
        set_setting(svc.enabled_key, "1" if enabled else "0")
        logger.info(f"Service {name} enabled={enabled}")
        return True

    def send_command(self, name: str, verb: str) -> bool:
        svc = self.get_service(name)
        if svc is None:
            return False
        raw = get_setting(svc.command_key, "")
        counter = 0
        if raw and ":" in raw:
            try:
                counter = int(raw.split(":", 1)[1])
            except ValueError:
                counter = 0
        set_setting(svc.command_key, f"{verb}:{counter + 1}")
        logger.info(f"Service {name} command={verb}")
        return True

    def save_config(self, name: str, form: dict) -> dict | None:
        svc = self.get_service(name)
        if svc is None:
            return None
        errors = {}
        valid = {}
        for field in svc.all_fields():
            if field.key not in form:
                continue
            raw = form[field.key]
            if field.secret and raw == "":
                continue
            try:
                valid[field.key] = field.to_storage(field.coerce(raw))
            except ValueError as e:
                errors[field.key] = str(e)
        for key, value in valid.items():
            set_setting(key, value)
        if valid:
            logger.info(f"Service {name} config saved ({len(valid)} fields)")
        if errors:
            return {"ok": False, "errors": errors, "saved": list(valid.keys())}
        return {"ok": True, "errors": {}, "saved": list(valid.keys())}

    def supervise(self) -> None:
        for svc in self._services.values():
            svc.start_supervisor()
            logger.info(f"Supervising service: {svc.name}")

    async def shutdown_all(self) -> None:
        tasks = []
        for svc in self._services.values():
            svc.request_shutdown()
            if svc._task is not None:
                svc._task.cancel()
                tasks.append(svc._task)
        if tasks:
            await asyncio.gather(*tasks, return_exceptions=True)
        logger.info("All services stopped")


service_manager = ServiceManager()
