"""Telemetry reporter — periodically publishes device metrics over MQTT.

Publishes to ``devices/{deviceId}/telemetry`` with battery, CPU, memory,
temperature, and agent status.
"""

from __future__ import annotations

import asyncio
import logging
import time
from typing import Any

from .client import MQTTManager

logger = logging.getLogger(__name__)


class TelemetryReporter:
    """Periodically reports device telemetry over MQTT."""

    def __init__(
        self,
        mqtt: MQTTManager,
        interval: float = 30.0,
        get_device_metrics: Any = None,
    ) -> None:
        self._mqtt = mqtt
        self._interval = interval
        self._get_device_metrics = get_device_metrics
        self._task: asyncio.Task[None] | None = None
        self._agent_status = "idle"

    @property
    def agent_status(self) -> str:
        return self._agent_status

    @agent_status.setter
    def agent_status(self, value: str) -> None:
        self._agent_status = value

    async def start(self) -> None:
        if self._task and not self._task.done():
            return
        self._task = asyncio.create_task(self._report_loop())

    async def stop(self) -> None:
        if self._task and not self._task.done():
            self._task.cancel()
            try:
                await self._task
            except asyncio.CancelledError:
                pass
            self._task = None

    async def _report_loop(self) -> None:
        try:
            while True:
                try:
                    await self._report_once()
                except Exception:
                    logger.exception("Telemetry report failed")
                await asyncio.sleep(self._interval)
        except asyncio.CancelledError:
            return

    async def _report_once(self) -> None:
        metrics: dict[str, Any] = {
            "timestamp": int(time.time()),
            "agent_status": self._agent_status,
        }

        if self._get_device_metrics:
            try:
                device_metrics = await self._get_device_metrics()
                metrics.update(device_metrics)
            except Exception:
                pass

        await self._mqtt.publish("telemetry", metrics)
