"""System metrics provider abstraction.

Wraps the per-platform metrics source so the rest of the codebase doesn't
need ``if psutil is not None`` guards at every call site. Selection
order in :func:`get_metrics_provider`:

1. :class:`AndroidMetricsProvider` — when running under Chaquopy and
   ``/proc/stat`` + ``/proc/meminfo`` are readable.
2. :class:`PsutilMetricsProvider` — desktop platforms with psutil.
3. :class:`NullMetricsProvider` — last-ditch fallback returning zeros.

Each provider lives in its own module — see ``psutil_provider.py``,
``android_provider.py``, ``null_provider.py``.
"""

from __future__ import annotations

from ledgrab.utils.platform import is_android

from .android_provider import AndroidMetricsProvider, is_supported as _android_supported
from .null_provider import NullMetricsProvider
from .psutil_provider import PsutilMetricsProvider
from .types import MemorySnapshot, MetricsProvider, ProcessSnapshot, ThermalSnapshot

__all__ = [
    "AndroidMetricsProvider",
    "MemorySnapshot",
    "MetricsProvider",
    "NullMetricsProvider",
    "ProcessSnapshot",
    "PsutilMetricsProvider",
    "ThermalSnapshot",
    "get_metrics_provider",
    "reset_metrics_provider",
]


_provider: MetricsProvider | None = None


def get_metrics_provider() -> MetricsProvider:
    """Return the process-wide metrics provider (created on first call).

    Idempotent — priming side effects inside providers run exactly once
    per process.
    """
    global _provider
    if _provider is None:
        if is_android() and _android_supported():
            _provider = AndroidMetricsProvider()
        else:
            try:
                import psutil
            except ImportError:
                _provider = NullMetricsProvider()
            else:
                _provider = PsutilMetricsProvider(psutil)
    return _provider


def reset_metrics_provider() -> None:
    """Reset the cached provider — for tests only."""
    global _provider
    _provider = None
