"""In-memory sort for server list items after Redis heartbeat overlay."""

from __future__ import annotations

from datetime import datetime, timezone
from typing import Any, Callable

LIVE_SORT_FIELDS = frozenset({"status", "heartbeat", "agent_version"})
MAX_LIVE_SORT_ROWS = 5000

_STATUS_ORDER = {"online": 0, "offline": 1, "unknown": 2}


def _parse_heartbeat(raw: Any) -> datetime | None:
    if not raw:
        return None
    text = str(raw).strip()
    if not text:
        return None
    try:
        if text.endswith("Z"):
            text = f"{text[:-1]}+00:00"
        dt = datetime.fromisoformat(text)
        if dt.tzinfo is None:
            dt = dt.replace(tzinfo=timezone.utc)
        return dt
    except (TypeError, ValueError):
        return None


def _status_key(item: dict[str, Any]) -> tuple[int, str]:
    status = item.get("status") or "unknown"
    rank = _STATUS_ORDER.get(status, 3)
    return rank, (item.get("name") or "").casefold()


def _heartbeat_key(item: dict[str, Any]) -> datetime | None:
    return _parse_heartbeat(item.get("last_heartbeat"))


def _agent_version_key(item: dict[str, Any]) -> str | None:
    ver = (item.get("agent_version") or "").strip()
    return ver or None


def _sort_with_nulls_last(
    items: list[dict[str, Any]],
    key_func: Callable[[dict[str, Any]], Any],
    *,
    reverse: bool,
) -> list[dict[str, Any]]:
    with_value: list[dict[str, Any]] = []
    without_value: list[dict[str, Any]] = []
    for item in items:
        if key_func(item) is None:
            without_value.append(item)
        else:
            with_value.append(item)
    with_value.sort(key=key_func, reverse=reverse)
    return with_value + without_value


def sort_server_items(
    items: list[dict[str, Any]],
    sort_by: str,
    sort_order: str = "asc",
) -> list[dict[str, Any]]:
    """Sort server dicts using live overlay fields (post-Redis)."""
    reverse = sort_order == "desc"
    if sort_by == "status":
        return sorted(items, key=_status_key, reverse=reverse)
    if sort_by == "heartbeat":
        return _sort_with_nulls_last(items, _heartbeat_key, reverse=reverse)
    if sort_by == "agent_version":
        return _sort_with_nulls_last(items, _agent_version_key, reverse=reverse)
    return items
