"""EHEIM Digital climate."""

from typing import Any

from eheimdigital.device import EheimDigitalDevice
from eheimdigital.heater import EheimDigitalHeater
from eheimdigital.types import HeaterMode, HeaterUnit

from homeassistant.components.climate import (
    PRESET_NONE,
    ClimateEntity,
    ClimateEntityFeature,
    HVACAction,
    HVACMode,
)
from homeassistant.const import (
    ATTR_TEMPERATURE,
    PRECISION_HALVES,
    PRECISION_TENTHS,
    UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .const import HEATER_BIO_MODE, HEATER_PRESET_TO_HEATER_MODE, HEATER_SMART_MODE
from .coordinator import EheimDigitalConfigEntry, EheimDigitalUpdateCoordinator
from .entity import EheimDigitalEntity, exception_handler

# Coordinator is used to centralize the data updates
PARALLEL_UPDATES = 0


async def async_setup_entry(
    hass: HomeAssistant,
    entry: EheimDigitalConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up the callbacks for the coordinator so climate entities can be added as devices are found."""
    coordinator = entry.runtime_data

    def async_setup_device_entities(
        device_address: dict[str, EheimDigitalDevice],
    ) -> None:
        """Set up the climate entities for one or multiple devices."""
        entities: list[EheimDigitalHeaterClimate] = []
        for device in device_address.values():
            if isinstance(device, EheimDigitalHeater):
                entities.append(EheimDigitalHeaterClimate(coordinator, device))
                coordinator.known_devices.add(device.mac_address)

        async_add_entities(entities)

    coordinator.add_platform_callback(async_setup_device_entities)

    async_setup_device_entities(coordinator.hub.devices)


class EheimDigitalHeaterClimate(EheimDigitalEntity[EheimDigitalHeater], ClimateEntity):
    """Represent an EHEIM Digital heater."""

    _attr_hvac_modes = [HVACMode.OFF, HVACMode.AUTO]
    _attr_hvac_mode = HVACMode.OFF
    _attr_precision = PRECISION_TENTHS
    _attr_supported_features = (
        ClimateEntityFeature.TARGET_TEMPERATURE
        | ClimateEntityFeature.TURN_ON
        | ClimateEntityFeature.TURN_OFF
        | ClimateEntityFeature.PRESET_MODE
    )
    _attr_target_temperature_step = PRECISION_HALVES
    _attr_preset_modes = [PRESET_NONE, HEATER_BIO_MODE, HEATER_SMART_MODE]
    _attr_temperature_unit = UnitOfTemperature.CELSIUS
    _attr_preset_mode = PRESET_NONE
    _attr_translation_key = "heater"
    _attr_name = None

    def __init__(
        self, coordinator: EheimDigitalUpdateCoordinator, device: EheimDigitalHeater
    ) -> None:
        """Initialize an EHEIM Digital thermocontrol climate entity."""
        super().__init__(coordinator, device)
        self._attr_unique_id = self._device_address
        self._async_update_attrs()

    @exception_handler
    async def async_set_preset_mode(self, preset_mode: str) -> None:
        """Set the preset mode."""
        if preset_mode in HEATER_PRESET_TO_HEATER_MODE:
            await self._device.set_operation_mode(
                HEATER_PRESET_TO_HEATER_MODE[preset_mode]
            )

    @exception_handler
    async def async_set_temperature(self, **kwargs: Any) -> None:
        """Set a new temperature."""
        if ATTR_TEMPERATURE in kwargs:
            await self._device.set_target_temperature(kwargs[ATTR_TEMPERATURE])

    @exception_handler
    async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
        """Set the heating mode."""
        match hvac_mode:
            case HVACMode.OFF:
                await self._device.set_active(active=False)
            case HVACMode.AUTO:
                await self._device.set_active(active=True)

    def _async_update_attrs(self) -> None:
        if self._device.temperature_unit == HeaterUnit.CELSIUS:
            self._attr_min_temp = 18
            self._attr_max_temp = 32
            self._attr_temperature_unit = UnitOfTemperature.CELSIUS
        elif self._device.temperature_unit == HeaterUnit.FAHRENHEIT:
            self._attr_min_temp = 64
            self._attr_max_temp = 90
            self._attr_temperature_unit = UnitOfTemperature.FAHRENHEIT

        self._attr_current_temperature = self._device.current_temperature
        self._attr_target_temperature = self._device.target_temperature

        if self._device.is_heating:
            self._attr_hvac_action = HVACAction.HEATING
            self._attr_hvac_mode = HVACMode.AUTO
        elif self._device.is_active:
            self._attr_hvac_action = HVACAction.IDLE
            self._attr_hvac_mode = HVACMode.AUTO
        else:
            self._attr_hvac_action = HVACAction.OFF
            self._attr_hvac_mode = HVACMode.OFF

        match self._device.operation_mode:
            case HeaterMode.MANUAL:
                self._attr_preset_mode = PRESET_NONE
            case HeaterMode.BIO:
                self._attr_preset_mode = HEATER_BIO_MODE
            case HeaterMode.SMART:
                self._attr_preset_mode = HEATER_SMART_MODE
