"""
Background status checker — parallel server pings.
"""

import threading
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from core.server_store import ServerStore

from core.ssh_client import SSHClientWrapper
from core.logger import log


class StatusChecker:
    def __init__(self, store: "ServerStore", interval: int = 60):
        self.store = store
        self.interval = interval
        self._running = False
        self._thread: threading.Thread | None = None
        self._gui_callback = None

    def start(self):
        if self._running:
            return
        self._running = True
        self._thread = threading.Thread(target=self._loop, daemon=True)
        self._thread.start()

    def stop(self):
        self._running = False
        if self._thread:
            self._thread.join(timeout=3.0)

    def set_gui_callback(self, callback):
        self._gui_callback = callback

    def check_one(self, server: dict) -> bool:
        key_path = self.store.get_ssh_key_path()
        wrapper = SSHClientWrapper(server, key_path)
        return wrapper.check_connection()

    def check_all_now(self):
        threading.Thread(target=self._check_cycle, daemon=True).start()

    def _loop(self):
        while self._running:
            self._check_cycle()
            for _ in range(self.interval * 10):
                if not self._running:
                    return
                time.sleep(0.1)

    def _check_cycle(self):
        servers = self.store.get_all()
        ssh_servers = [s for s in servers if s.get("type", "ssh") == "ssh"]

        # Mark non-SSH as unknown
        for s in servers:
            if s.get("type", "ssh") != "ssh":
                self.store.set_status(s["alias"], "unknown")

        if not ssh_servers:
            return

        # Parallel checks — up to 10 concurrent
        max_workers = min(10, len(ssh_servers))
        try:
            with ThreadPoolExecutor(max_workers=max_workers) as executor:
                futures = {
                    executor.submit(self.check_one, s): s["alias"]
                    for s in ssh_servers
                }
                for future in as_completed(futures, timeout=30):
                    if not self._running:
                        return
                    alias = futures[future]
                    try:
                        online = future.result(timeout=10)
                        self.store.set_status(alias, "online" if online else "offline")
                    except Exception:
                        self.store.set_status(alias, "offline")
        except Exception as e:
            log.warning(f"Status check cycle error: {e}")

        if self._gui_callback:
            try:
                self._gui_callback()
            except Exception:
                pass
