"""Central Nexus Agent version (SSOT) and semver-style comparison."""

from __future__ import annotations

import re
from functools import lru_cache
from pathlib import Path

_AGENT_PY = Path(__file__).resolve().parents[2] / "web" / "agent" / "agent.py"
_AGENT_VERSION_CONST_RE = re.compile(r'^AGENT_VERSION\s*=\s*"([^"]+)"', re.MULTILINE)


@lru_cache(maxsize=1)
def get_central_agent_version() -> str:
    """Read AGENT_VERSION constant from web/agent/agent.py (heartbeat SSOT)."""
    text = _AGENT_PY.read_text(encoding="utf-8")
    match = _AGENT_VERSION_CONST_RE.search(text)
    if not match:
        raise RuntimeError(f"AGENT_VERSION not found in {_AGENT_PY}")
    return match.group(1)


def version_tuple(version: str) -> tuple[int, ...]:
    """Parse dotted numeric prefix, e.g. 2.0.0 -> (2, 0, 0)."""
    version = (version or "").strip()
    if not version:
        return ()
    parts: list[int] = []
    for segment in re.split(r"[.-]", version):
        if segment.isdigit():
            parts.append(int(segment))
        else:
            break
    return tuple(parts)


def is_version_lower(remote: str, central: str) -> bool:
    """True when remote is strictly older than central."""
    remote_t = version_tuple(remote)
    central_t = version_tuple(central)
    if not remote_t:
        return True
    if not central_t:
        return False
    return remote_t < central_t


def is_version_at_least(remote: str, central: str) -> bool:
    """True when remote >= central (equal counts as skip)."""
    remote_t = version_tuple(remote)
    central_t = version_tuple(central)
    if not remote_t:
        return False
    if not central_t:
        return bool(remote_t)
    return remote_t >= central_t


def agent_is_installed(
    *,
    agent_version_db: str | None,
    heartbeat: dict[str, str] | None = None,
) -> bool:
    """True when Agent has reported a version or heartbeat (not merely a DB API key)."""
    if heartbeat:
        if (heartbeat.get("agent_version") or "").strip():
            return True
        if heartbeat.get("last_heartbeat"):
            return True
    return bool((agent_version_db or "").strip())


def compute_agent_guidance(
    *,
    agent_version_db: str | None,
    heartbeat: dict[str, str] | None = None,
    central: str | None = None,
) -> dict[str, str | None]:
    """UI hints: install / upgrade / offline / ok."""
    central_v = central or get_central_agent_version()
    live_ver = ""
    if heartbeat:
        live_ver = (heartbeat.get("agent_version") or "").strip()
    if not live_ver:
        live_ver = (agent_version_db or "").strip()

    has_heartbeat = bool(heartbeat and heartbeat.get("last_heartbeat"))
    installed = agent_is_installed(agent_version_db=agent_version_db, heartbeat=heartbeat)

    base: dict[str, str | None] = {
        "central_agent_version": central_v,
        "agent_action": "ok",
        "agent_action_message": None,
    }

    if not installed:
        return {
            **base,
            "agent_action": "install",
            "agent_action_message": (
                f"尚未安装 Agent（主站版本 {central_v}）。"
                "安装后可自动上报 CPU/内存/磁盘与在线状态；未安装时仅能通过 SSH 手动探活。"
            ),
        }

    if live_ver and is_version_lower(live_ver, central_v):
        return {
            **base,
            "agent_action": "upgrade",
            "agent_action_message": (
                f"当前 Agent {live_ver}，低于主站 {central_v}，建议升级以获取最新心跳与探针能力。"
            ),
        }

    if not has_heartbeat:
        return {
            **base,
            "agent_action": "offline",
            "agent_action_message": (
                "Agent 已登记但暂无心跳，请检查子机 nexus-agent 服务或点击「诊断」。"
            ),
        }

    return base
