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

from __future__ import annotations

import logging
from typing import Any

from huum.const import SaunaStatus
from huum.exceptions import SafetyException
from huum.huum import Huum
from huum.schemas import HuumStatusResponse

from homeassistant.components.climate import (
    ClimateEntity,
    ClimateEntityFeature,
    HVACMode,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(
    hass: HomeAssistant,
    entry: ConfigEntry,
    async_add_entities: AddEntitiesCallback,
) -> None:
    """Set up the Huum sauna with config flow."""
    huum_handler = hass.data.setdefault(DOMAIN, {})[entry.entry_id]

    async_add_entities([HuumDevice(huum_handler, entry.entry_id)], True)


class HuumDevice(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_max_temp = 110
    _attr_min_temp = 40
    _attr_has_entity_name = True
    _attr_name = None

    _target_temperature: int | None = None
    _status: HuumStatusResponse | None = None
    _enable_turn_on_off_backwards_compatibility = False

    def __init__(self, huum_handler: Huum, unique_id: str) -> None:
        """Initialize the heater."""
        self._attr_unique_id = unique_id
        self._attr_device_info = DeviceInfo(
            identifiers={(DOMAIN, unique_id)},
            name="Huum sauna",
            manufacturer="Huum",
        )

        self._huum_handler = huum_handler

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

    @property
    def icon(self) -> str:
        """Return nice icon for heater."""
        if self.hvac_mode == HVACMode.HEAT:
            return "mdi:radiator"
        return "mdi:radiator-off"

    @property
    def current_temperature(self) -> int | None:
        """Return the current temperature."""
        if (status := self._status) is not None:
            return status.temperature
        return None

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

    async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
        """Set hvac mode."""
        if hvac_mode == HVACMode.HEAT:
            await self._turn_on(self.target_temperature)
        elif hvac_mode == HVACMode.OFF:
            await self._huum_handler.turn_off()

    async def async_set_temperature(self, **kwargs: Any) -> None:
        """Set new target temperature."""
        temperature = kwargs.get(ATTR_TEMPERATURE)
        if temperature is None:
            return
        self._target_temperature = temperature

        if self.hvac_mode == HVACMode.HEAT:
            await self._turn_on(temperature)

    async def async_update(self) -> None:
        """Get the latest status data.

        We get the latest status first from the status endpoints of the sauna.
        If that data does not include the temperature, that means that the sauna
        is off, we then call the off command which will in turn return the temperature.
        This is a workaround for getting the temperature as the Huum API does not
        return the target temperature of a sauna that is off, even if it can have
        a target temperature at that time.
        """
        self._status = await self._huum_handler.status_from_status_or_stop()
        if self._target_temperature is None or self.hvac_mode == HVACMode.HEAT:
            self._target_temperature = self._status.target_temperature

    async def _turn_on(self, temperature: int) -> None:
        try:
            await self._huum_handler.turn_on(temperature)
        except (ValueError, SafetyException) as err:
            _LOGGER.error(str(err))
            raise HomeAssistantError(f"Unable to turn on sauna: {err}") from err
