"""psutil-backed metrics provider for desktop platforms."""

from __future__ import annotations

import os

from .types import MemorySnapshot, ProcessSnapshot, ThermalSnapshot


class PsutilMetricsProvider:
    """psutil-backed provider for Windows/macOS/Linux desktop hosts.

    Primes psutil's interval-based CPU counters at construction so the
    first real sample returns a meaningful value instead of 0.0. The
    logical CPU count is cached because it never changes during a
    process's lifetime.
    """

    available: bool = True

    def __init__(self, psutil_module) -> None:
        self._psutil = psutil_module
        psutil_module.cpu_percent(interval=None)
        self._process = psutil_module.Process(os.getpid())
        self._process.cpu_percent(interval=None)
        self._cpu_count = int(psutil_module.cpu_count(logical=True) or 1)

    def cpu_percent(self) -> float:
        return float(self._psutil.cpu_percent(interval=None))

    def cpu_count(self) -> int:
        return self._cpu_count

    def virtual_memory(self) -> MemorySnapshot:
        m = self._psutil.virtual_memory()
        return MemorySnapshot(
            used_bytes=int(m.used),
            total_bytes=int(m.total),
            percent=float(m.percent),
        )

    def process_snapshot(self) -> ProcessSnapshot:
        # psutil's Process.cpu_percent() returns 0–N*100%; normalize to 0–100%.
        cpu = self._process.cpu_percent(interval=None) / self._cpu_count
        rss = int(self._process.memory_info().rss)
        return ProcessSnapshot(cpu_percent=float(cpu), rss_bytes=rss)

    def thermals(self) -> ThermalSnapshot:
        battery_pct: float | None = None
        battery_temp: float | None = None
        cpu_temp: float | None = None

        # Battery: only some hosts report it (laptops, tablets); psutil
        # raises or returns None on desktops without a battery.
        sensors_battery = getattr(self._psutil, "sensors_battery", None)
        if sensors_battery is not None:
            try:
                bat = sensors_battery()
                if bat is not None:
                    battery_pct = float(bat.percent)
            except Exception:
                pass

        # CPU temperature: pick the hottest reading across all sensors.
        # sensors_temperatures() is Linux-only on psutil; absent on Win/macOS.
        sensors_temps = getattr(self._psutil, "sensors_temperatures", None)
        if sensors_temps is not None:
            try:
                temps = sensors_temps()
                hottest = None
                for entries in (temps or {}).values():
                    for entry in entries:
                        current = getattr(entry, "current", None)
                        if current is None:
                            continue
                        if hottest is None or current > hottest:
                            hottest = float(current)
                if hottest is not None:
                    cpu_temp = hottest
            except Exception:
                pass

        return ThermalSnapshot(
            battery_percent=battery_pct,
            battery_temp_c=battery_temp,
            cpu_temp_c=cpu_temp,
        )
