"""Number entity platform for Tailwind."""

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

from gotailwind import Tailwind, TailwindDeviceStatus, TailwindError

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

from .const import DOMAIN
from .coordinator import TailwindConfigEntry
from .entity import TailwindEntity

PARALLEL_UPDATES = 1


@dataclass(frozen=True, kw_only=True)
class TailwindNumberEntityDescription(NumberEntityDescription):
    """Class describing Tailwind number entities."""

    value_fn: Callable[[TailwindDeviceStatus], int]
    set_value_fn: Callable[[Tailwind, float], Awaitable[Any]]


DESCRIPTIONS = [
    TailwindNumberEntityDescription(
        key="brightness",
        translation_key="brightness",
        entity_category=EntityCategory.CONFIG,
        native_step=1,
        native_min_value=0,
        native_max_value=100,
        native_unit_of_measurement=PERCENTAGE,
        value_fn=lambda data: data.led_brightness,
        set_value_fn=lambda tailwind, brightness: tailwind.status_led(
            brightness=int(brightness),
        ),
    ),
]


async def async_setup_entry(
    hass: HomeAssistant,
    entry: TailwindConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up Tailwind number based on a config entry."""
    async_add_entities(
        TailwindNumberEntity(
            entry.runtime_data,
            description,
        )
        for description in DESCRIPTIONS
    )


class TailwindNumberEntity(TailwindEntity, NumberEntity):
    """Representation of a Tailwind number entity."""

    entity_description: TailwindNumberEntityDescription

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

    @override
    async def async_set_native_value(self, value: float) -> None:
        """Change to new number value."""
        try:
            await self.entity_description.set_value_fn(self.coordinator.tailwind, value)
        except TailwindError as exc:
            raise HomeAssistantError(
                translation_domain=DOMAIN,
                translation_key="communication_error",
            ) from exc
        await self.coordinator.async_request_refresh()
