"""Per-server metric parsing and offline segment merging."""

from __future__ import annotations

import json
from typing import Any

from server.utils.fleet_metrics import _metric_from_system_info


def parse_system_info_metrics(system_info: dict[str, Any] | str | None) -> tuple[int | None, int | None]:
    """Extract CPU/mem integer percentages from Agent system_info."""
    if system_info is None:
        return None, None
    info: dict[str, Any]
    if isinstance(system_info, str):
        try:
            parsed = json.loads(system_info)
        except json.JSONDecodeError:
            return None, None
        info = parsed if isinstance(parsed, dict) else {}
    elif isinstance(system_info, dict):
        info = system_info
    else:
        return None, None

    cpu = _metric_from_system_info(info, "cpu_usage", "cpu")
    mem = _metric_from_system_info(info, "mem_usage", "mem")
    cpu_i = round(cpu) if cpu is not None else None
    mem_i = round(mem) if mem is not None else None
    return cpu_i, mem_i


def sample_from_redis_heartbeat(data: dict[str, Any]) -> tuple[bool, int | None, int | None]:
    """Map Redis heartbeat hash to (is_online, cpu_pct, mem_pct) for one flush sample."""
    is_online = data.get("is_online") == "True"
    if not is_online:
        return False, None, None
    cpu, mem = parse_system_info_metrics(data.get("system_info"))
    return True, cpu, mem


def merge_offline_segments(points: list[dict[str, Any]]) -> list[dict[str, str]]:
    """Merge consecutive is_online=false points into {from, to} segments (recorded_at strings)."""
    if not points:
        return []

    segments: list[dict[str, str]] = []
    seg_start: str | None = None
    prev_at: str | None = None

    for point in points:
        recorded_at = str(point.get("recorded_at") or "")
        if not recorded_at:
            continue
        is_online = bool(point.get("is_online"))
        if not is_online:
            if seg_start is None:
                seg_start = recorded_at
        elif seg_start is not None and prev_at is not None:
            segments.append({"from": seg_start, "to": prev_at})
            seg_start = None
        prev_at = recorded_at

    if seg_start is not None and prev_at is not None:
        segments.append({"from": seg_start, "to": prev_at})

    return segments
