"""Define an object to manage fetching AirGradient data."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import timedelta

from airgradient import AirGradientClient, AirGradientError, Config, Measures

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import DOMAIN, LOGGER

type AirGradientConfigEntry = ConfigEntry[AirGradientCoordinator]


@dataclass
class AirGradientData:
    """Class for AirGradient data."""

    measures: Measures
    config: Config


class AirGradientCoordinator(DataUpdateCoordinator[AirGradientData]):
    """Class to manage fetching AirGradient data."""

    config_entry: AirGradientConfigEntry
    _current_version: str

    def __init__(
        self,
        hass: HomeAssistant,
        config_entry: AirGradientConfigEntry,
        client: AirGradientClient,
    ) -> None:
        """Initialize coordinator."""
        super().__init__(
            hass,
            logger=LOGGER,
            config_entry=config_entry,
            name=f"AirGradient {client.host}",
            update_interval=timedelta(minutes=1),
        )
        self.client = client
        assert self.config_entry.unique_id
        self.serial_number = self.config_entry.unique_id

    async def _async_setup(self) -> None:
        """Set up the coordinator."""
        try:
            self._current_version = (
                await self.client.get_current_measures()
            ).firmware_version
        except AirGradientError as error:
            raise UpdateFailed(
                translation_domain=DOMAIN,
                translation_key="update_error",
                translation_placeholders={"error": str(error)},
            ) from error

    async def _async_update_data(self) -> AirGradientData:
        try:
            measures = await self.client.get_current_measures()
            config = await self.client.get_config()
        except AirGradientError as error:
            raise UpdateFailed(
                translation_domain=DOMAIN,
                translation_key="update_error",
                translation_placeholders={"error": str(error)},
            ) from error
        if measures.firmware_version != self._current_version:
            device_registry = dr.async_get(self.hass)
            device_entry = device_registry.async_get_device(
                identifiers={(DOMAIN, self.serial_number)}
            )
            assert device_entry
            device_registry.async_update_device(
                device_entry.id,
                sw_version=measures.firmware_version,
            )
            self._current_version = measures.firmware_version
        return AirGradientData(measures, config)
