"""Support for Huum wifi-enabled sauna."""

from typing import Any, override

from huum.const import SaunaStatus
from huum.exceptions import SafetyException

from homeassistant.components.climate import (
    ClimateEntity,
    ClimateEntityFeature,
    HVACMode,
)
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .const import CONFIG_DEFAULT_MAX_TEMP, CONFIG_DEFAULT_MIN_TEMP, DOMAIN
from .coordinator import HuumConfigEntry, HuumDataUpdateCoordinator
from .entity import HuumBaseEntity

PARALLEL_UPDATES = 1


async def async_setup_entry(
    hass: HomeAssistant,
    entry: HuumConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up the Huum sauna with config flow."""
    async_add_entities([HuumDevice(entry.runtime_data)])


class HuumDevice(HuumBaseEntity, ClimateEntity):
    """Representation of a heater."""

    _attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF]
    _attr_supported_features = (
        ClimateEntityFeature.TARGET_TEMPERATURE
        | ClimateEntityFeature.TURN_OFF
        | ClimateEntityFeature.TURN_ON
    )
    _attr_target_temperature_step = PRECISION_WHOLE
    _attr_temperature_unit = UnitOfTemperature.CELSIUS
    _attr_name = None

    def __init__(self, coordinator: HuumDataUpdateCoordinator) -> None:
        """Initialize the heater."""
        super().__init__(coordinator)

        self._attr_unique_id = coordinator.config_entry.entry_id

    @property
    @override
    def min_temp(self) -> int:
        """Return configured minimal temperature."""
        sauna_config = self.coordinator.data.sauna_config
        if sauna_config is None:
            return CONFIG_DEFAULT_MIN_TEMP
        return sauna_config.min_temp or CONFIG_DEFAULT_MIN_TEMP

    @property
    @override
    def max_temp(self) -> int:
        """Return configured maximum temperature."""
        sauna_config = self.coordinator.data.sauna_config
        if sauna_config is None:
            return CONFIG_DEFAULT_MAX_TEMP
        return sauna_config.max_temp or CONFIG_DEFAULT_MAX_TEMP

    @property
    @override
    def hvac_mode(self) -> HVACMode:
        """Return hvac operation ie. heat, cool mode."""
        if self.coordinator.data.status == SaunaStatus.ONLINE_HEATING:
            return HVACMode.HEAT
        return HVACMode.OFF

    @property
    @override
    def current_temperature(self) -> int | None:
        """Return the current temperature."""
        return self.coordinator.data.temperature

    @property
    @override
    def target_temperature(self) -> int:
        """Return the temperature we try to reach."""
        return self.coordinator.data.target_temperature or int(self.min_temp)

    @override
    async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
        """Set hvac mode."""
        if hvac_mode == HVACMode.HEAT:
            # Make sure to send integers
            # The temperature is not always an integer if the user uses Fahrenheit
            temperature = int(self.target_temperature)
            await self._turn_on(temperature)
        elif hvac_mode == HVACMode.OFF:
            await self.coordinator.huum.turn_off()
        await self.coordinator.async_refresh()

    @override
    async def async_set_temperature(self, **kwargs: Any) -> None:
        """Set new target temperature."""
        temperature = kwargs.get(ATTR_TEMPERATURE)
        if temperature is None or self.hvac_mode != HVACMode.HEAT:
            return
        temperature = int(temperature)

        await self._turn_on(temperature)
        await self.coordinator.async_refresh()

    async def _turn_on(self, temperature: int) -> None:
        try:
            await self.coordinator.huum.turn_on(temperature)
        except (ValueError, SafetyException) as err:
            raise HomeAssistantError(
                translation_domain=DOMAIN,
                translation_key="unable_to_turn_on",
            ) from err
