"""DataUpdate Coordinator, and base Entity and Device models for Toon."""

from dataclasses import dataclass
from typing import override

from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN
from .coordinator import ToonDataUpdateCoordinator


class ToonEntity(CoordinatorEntity[ToonDataUpdateCoordinator]):
    """Defines a base Toon entity."""


class ToonDisplayDeviceEntity(ToonEntity):
    """Defines a Toon display device entity."""

    @property
    @override
    def device_info(self) -> DeviceInfo:
        """Return device information about this thermostat."""
        agreement = self.coordinator.data.agreement
        return DeviceInfo(
            identifiers={(DOMAIN, agreement.agreement_id)},
            manufacturer="Eneco",
            model=agreement.display_hardware_version.rpartition("/")[0],
            name="Toon Display",
            sw_version=agreement.display_software_version.rpartition("/")[-1],
        )


class ToonElectricityMeterDeviceEntity(ToonEntity):
    """Defines a Electricity Meter device entity."""

    @property
    @override
    def device_info(self) -> DeviceInfo:
        """Return device information about this entity."""
        agreement_id = self.coordinator.data.agreement.agreement_id
        return DeviceInfo(
            name="Electricity Meter",
            identifiers={
                (DOMAIN, agreement_id, "electricity"),  # type: ignore[arg-type]
            },
            via_device_id=dr.async_get_device_id_by_identifier(
                self.coordinator.hass,
                (DOMAIN, agreement_id, "meter_adapter"),  # type: ignore[arg-type]
                config_entry_id=self.coordinator.config_entry.entry_id,
            ),
        )


class ToonGasMeterDeviceEntity(ToonEntity):
    """Defines a Gas Meter device entity."""

    @property
    @override
    def device_info(self) -> DeviceInfo:
        """Return device information about this entity."""
        agreement_id = self.coordinator.data.agreement.agreement_id
        return DeviceInfo(
            name="Gas Meter",
            identifiers={
                (DOMAIN, agreement_id, "gas"),  # type: ignore[arg-type]
            },
            via_device_id=dr.async_get_device_id_by_identifier(
                self.coordinator.hass,
                (DOMAIN, agreement_id, "electricity"),  # type: ignore[arg-type]
                config_entry_id=self.coordinator.config_entry.entry_id,
            ),
        )


class ToonWaterMeterDeviceEntity(ToonEntity):
    """Defines a Water Meter device entity."""

    @property
    @override
    def device_info(self) -> DeviceInfo:
        """Return device information about this entity."""
        agreement_id = self.coordinator.data.agreement.agreement_id
        return DeviceInfo(
            name="Water Meter",
            identifiers={
                (DOMAIN, agreement_id, "water"),  # type: ignore[arg-type]
            },
            via_device_id=dr.async_get_device_id_by_identifier(
                self.coordinator.hass,
                (DOMAIN, agreement_id, "electricity"),  # type: ignore[arg-type]
                config_entry_id=self.coordinator.config_entry.entry_id,
            ),
        )


class ToonSolarDeviceEntity(ToonEntity):
    """Defines a Solar Device device entity."""

    @property
    @override
    def device_info(self) -> DeviceInfo:
        """Return device information about this entity."""
        agreement_id = self.coordinator.data.agreement.agreement_id
        return DeviceInfo(
            name="Solar Panels",
            identifiers={
                (DOMAIN, agreement_id, "solar"),  # type: ignore[arg-type]
            },
            via_device_id=dr.async_get_device_id_by_identifier(
                self.coordinator.hass,
                (DOMAIN, agreement_id, "meter_adapter"),  # type: ignore[arg-type]
                config_entry_id=self.coordinator.config_entry.entry_id,
            ),
        )


class ToonBoilerModuleDeviceEntity(ToonEntity):
    """Defines a Boiler Module device entity."""

    @property
    @override
    def device_info(self) -> DeviceInfo:
        """Return device information about this entity."""
        agreement_id = self.coordinator.data.agreement.agreement_id
        return DeviceInfo(
            name="Boiler Module",
            manufacturer="Eneco",
            identifiers={
                (
                    DOMAIN,
                    agreement_id,  # type: ignore[arg-type]
                    "boiler_module",
                )
            },
            via_device_id=dr.async_get_device_id_by_identifier(
                self.coordinator.hass,
                (DOMAIN, agreement_id),
                config_entry_id=self.coordinator.config_entry.entry_id,
            ),
        )


class ToonBoilerDeviceEntity(ToonEntity):
    """Defines a Boiler device entity."""

    @property
    @override
    def device_info(self) -> DeviceInfo:
        """Return device information about this entity."""
        agreement_id = self.coordinator.data.agreement.agreement_id
        return DeviceInfo(
            name="Boiler",
            identifiers={
                (DOMAIN, agreement_id, "boiler"),  # type: ignore[arg-type]
            },
            via_device_id=dr.async_get_device_id_by_identifier(
                self.coordinator.hass,
                (DOMAIN, agreement_id, "boiler_module"),  # type: ignore[arg-type]
                config_entry_id=self.coordinator.config_entry.entry_id,
            ),
        )


@dataclass(frozen=True)
class ToonRequiredKeysMixin:
    """Mixin for required keys."""

    section: str
    measurement: str
