"""Nexus — Server Service (Business logic for server management)
Application layer — orchestrates Repository + SSH pool + Redis cache.
"""

import asyncio
import json
import logging
from typing import Optional, List, Dict

from server.domain.models import Server
from server.domain.repositories import ServerRepository, SyncLogRepository

logger = logging.getLogger("nexus.server_service")


class ServerService:
    """Business logic for server CRUD, health check, and push operations"""

    def __init__(self, server_repo: ServerRepository, sync_log_repo: SyncLogRepository):
        self.server_repo = server_repo
        self.sync_log_repo = sync_log_repo

    async def get_server(self, id: int) -> Optional[Server]:
        return await self.server_repo.get_by_id(id)

    async def create_server(self, server: Server) -> Server:
        return await self.server_repo.create(server)

    async def update_server(self, server: Server) -> Server:
        return await self.server_repo.update(server)

    async def delete_server(self, id: int) -> bool:
        return await self.server_repo.delete(id)

    async def update_heartbeat(self, id: int, data: dict) -> None:
        """Process Agent heartbeat data"""
        is_online = data.get("is_online", True)
        system_info = json.dumps(data.get("system_info", {}))
        agent_version = data.get("agent_version", "")
        await self.server_repo.update_heartbeat(id, is_online, system_info, agent_version)

    async def check_all_servers(self, server_ids: List[int]) -> Dict[int, dict]:
        """Check health of multiple servers via SSH (no Agent port 8601 required)."""
        from server.infrastructure.ssh.remote_probe import ssh_health_probe

        results = {}

        async def _check_one(server: Server) -> tuple:
            try:
                probe = await ssh_health_probe(server, timeout=15)
                return server.id, probe
            except Exception as e:
                return server.id, {"status": "offline", "error": str(e)[:200], "channel": "ssh"}

        servers = []
        for sid in server_ids:
            server = await self.server_repo.get_by_id(sid)
            if server:
                servers.append(server)
            else:
                results[sid] = {"status": "not_found"}

        if servers:
            check_results = await asyncio.gather(*[_check_one(s) for s in servers])
            for sid, result in check_results:
                results[sid] = result

        return results