"""Orchestrator system metrics in WESP admin-panel shape."""

from __future__ import annotations

import os
import time
from typing import Any

_NET_STATE: dict[str, float | int] | None = None


def _human_uptime(seconds: int | None) -> str | None:
    if seconds is None:
        return None
    sec = max(0, int(seconds))
    days, rem = divmod(sec, 86400)
    hours, rem = divmod(rem, 3600)
    minutes, _ = divmod(rem, 60)
    parts: list[str] = []
    if days:
        parts.append(f"{days}d")
    if hours or days:
        parts.append(f"{hours}h")
    parts.append(f"{minutes}m")
    return " ".join(parts)


def collect_orchestrator_system_metrics() -> dict[str, Any]:
    try:
        import psutil  # type: ignore[import-untyped]
    except ImportError:
        return {
            "available": False,
            "message": "Установите пакет psutil (pip install psutil) для метрик CPU/RAM/диска.",
        }

    global _NET_STATE
    now = time.time()
    boot_t = float(psutil.boot_time())
    host_uptime_sec = int(max(0.0, now - boot_t))

    proc_uptime_sec = None
    try:
        proc = psutil.Process()
        proc_uptime_sec = int(max(0.0, now - float(proc.create_time())))
    except Exception:
        pass

    vm = psutil.virtual_memory()
    sw = psutil.swap_memory()

    disk_block: dict[str, Any] | None
    try:
        du = psutil.disk_usage("/")
        disk_block = {
            "path": "/",
            "used": int(du.used),
            "total": int(du.total),
            "percent": round(du.percent, 2),
        }
    except OSError:
        disk_block = None

    load_avg = None
    try:
        load_avg = [round(x, 2) for x in os.getloadavg()]
    except (OSError, AttributeError):
        pass

    net = psutil.net_io_counters()
    upload_bps = 0.0
    download_bps = 0.0
    if _NET_STATE is not None and now > float(_NET_STATE["t"]):
        dt = now - float(_NET_STATE["t"])
        if dt > 0:
            upload_bps = max(0.0, (int(net.bytes_sent) - int(_NET_STATE["sent"])) / dt)
            download_bps = max(0.0, (int(net.bytes_recv) - int(_NET_STATE["recv"])) / dt)
    _NET_STATE = {"t": now, "sent": int(net.bytes_sent), "recv": int(net.bytes_recv)}

    conn_counts: dict[str, Any] = {"tcp": "—", "udp": "—"}
    try:
        conn_counts = {
            "tcp": len(psutil.net_connections(kind="tcp")),
            "udp": len(psutil.net_connections(kind="udp")),
        }
    except Exception:
        pass

    addresses: list[dict[str, Any]] = []
    try:
        for name, addrs in psutil.net_if_addrs().items():
            for addr in addrs:
                if getattr(addr, "family", None) and str(getattr(addr, "address", "")).strip():
                    addresses.append({"iface": name, "address": addr.address})
    except Exception:
        pass

    return {
        "available": True,
        "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(int(now))),
        "host": {
            "boot_time_unix": int(boot_t),
            "uptime_seconds": host_uptime_sec,
            "uptime_human": _human_uptime(host_uptime_sec),
        },
        "process": {
            "pid": os.getpid(),
            "uptime_seconds": proc_uptime_sec,
            "uptime_human": _human_uptime(proc_uptime_sec) if proc_uptime_sec is not None else None,
        },
        "cpu": {
            "percent": round(float(psutil.cpu_percent(interval=0.1)), 2),
            "cores": int(psutil.cpu_count(logical=True) or 1),
        },
        "memory": {
            "used": int(vm.used),
            "total": int(vm.total),
            "percent": round(vm.percent, 2),
        },
        "swap": {
            "used": int(sw.used),
            "total": int(sw.total),
            "percent": round(sw.percent, 2) if sw.total else 0.0,
        },
        "disk": disk_block,
        "network": {
            "upload_bps": round(upload_bps, 2),
            "download_bps": round(download_bps, 2),
            "bytes_sent_total": int(net.bytes_sent),
            "bytes_recv_total": int(net.bytes_recv),
        },
        "load_avg": load_avg,
        "connections": conn_counts,
        "addresses": addresses,
    }
