"""Support for Fumis number entities."""

from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any, override

from fumis import Fumis, FumisInfo

from homeassistant.components.number import NumberEntity, NumberEntityDescription
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .coordinator import FumisConfigEntry, FumisDataUpdateCoordinator
from .entity import FumisEntity
from .helpers import fumis_exception_handler

PARALLEL_UPDATES = 1


@dataclass(frozen=True, kw_only=True)
class FumisNumberEntityDescription(NumberEntityDescription):
    """Describes a Fumis number entity."""

    has_fn: Callable[[FumisInfo], bool] = lambda _: True
    value_fn: Callable[[FumisInfo], float | None]
    set_fn: Callable[[Fumis, float], Awaitable[Any]]


NUMBERS: tuple[FumisNumberEntityDescription, ...] = (
    FumisNumberEntityDescription(
        key="fan_speed",
        translation_key="fan_speed",
        entity_category=EntityCategory.CONFIG,
        entity_registry_enabled_default=False,
        native_min_value=0,
        native_max_value=5,
        native_step=1,
        has_fn=lambda data: len(data.controller.fans) > 0,
        value_fn=lambda data: (
            data.controller.fans[0].speed if data.controller.fans else None
        ),
        set_fn=lambda client, value: client.set_fan_speed(int(value)),
    ),
    FumisNumberEntityDescription(
        key="power_level",
        translation_key="power_level",
        native_min_value=1,
        native_max_value=5,
        native_step=1,
        value_fn=lambda data: data.controller.power.set_power,
        set_fn=lambda client, value: client.set_power(int(value)),
    ),
)


async def async_setup_entry(
    hass: HomeAssistant,
    entry: FumisConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up Fumis number entities based on a config entry."""
    coordinator = entry.runtime_data
    async_add_entities(
        FumisNumberEntity(coordinator=coordinator, description=description)
        for description in NUMBERS
        if description.has_fn(coordinator.data)
    )


class FumisNumberEntity(FumisEntity, NumberEntity):
    """Defines a Fumis number entity."""

    entity_description: FumisNumberEntityDescription

    def __init__(
        self,
        coordinator: FumisDataUpdateCoordinator,
        description: FumisNumberEntityDescription,
    ) -> None:
        """Initialize the Fumis number entity."""
        super().__init__(coordinator)
        self.entity_description = description
        self._attr_unique_id = f"{coordinator.config_entry.unique_id}_{description.key}"

    @property
    @override
    def native_value(self) -> float | None:
        """Return the current value."""
        return self.entity_description.value_fn(self.coordinator.data)

    @fumis_exception_handler
    @override
    async def async_set_native_value(self, value: float) -> None:
        """Set a new value."""
        await self.entity_description.set_fn(self.coordinator.client, value)
        await self.coordinator.async_request_refresh()
