"""Support for hunterdouglas_powerview numbers."""

from collections.abc import Callable
from dataclasses import dataclass
import logging
from typing import Final

from aiopvapi.helpers.constants import ATTR_NAME, MOTION_VELOCITY
from aiopvapi.resources.shade import BaseShade, ShadePosition

from homeassistant.components.number import (
    NumberEntityDescription,
    NumberMode,
    RestoreNumber,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import DOMAIN
from .coordinator import PowerviewShadeUpdateCoordinator
from .entity import ShadeEntity
from .model import PowerviewDeviceInfo, PowerviewEntryData

_LOGGER = logging.getLogger(__name__)


@dataclass(frozen=True, kw_only=True)
class PowerviewNumberDescription(NumberEntityDescription):
    """Class to describe a Number entity."""

    create_entity_fn: Callable[[BaseShade], bool]
    store_value_fn: Callable[[PowerviewShadeUpdateCoordinator, int, float | None], None]
    entity_category: EntityCategory = EntityCategory.CONFIG


def store_velocity(
    coordinator: PowerviewShadeUpdateCoordinator,
    shade_id: int,
    value: float | None,
) -> None:
    """Store the desired shade velocity in the coordinator."""
    coordinator.data.update_shade_velocity(shade_id, ShadePosition(velocity=value))


NUMBERS: Final = (
    PowerviewNumberDescription(
        key="velocity",
        name="Velocity",
        mode=NumberMode.SLIDER,
        icon="mdi:speedometer",
        create_entity_fn=lambda shade: shade.is_supported(MOTION_VELOCITY),
        store_value_fn=store_velocity,
    ),
)


async def async_setup_entry(
    hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
    """Set up the hunter douglas number entities."""

    pv_entry: PowerviewEntryData = hass.data[DOMAIN][entry.entry_id]

    entities: list[PowerViewNumber] = []
    for shade in pv_entry.shade_data.values():
        room_name = getattr(pv_entry.room_data.get(shade.room_id), ATTR_NAME, "")
        entities.extend(
            PowerViewNumber(
                pv_entry.coordinator,
                pv_entry.device_info,
                room_name,
                shade,
                shade.name,
                description,
            )
            for description in NUMBERS
            if description.create_entity_fn(shade)
        )
    async_add_entities(entities)


class PowerViewNumber(ShadeEntity, RestoreNumber):
    """Representation of a number entity."""

    entity_description: PowerviewNumberDescription

    def __init__(
        self,
        coordinator: PowerviewShadeUpdateCoordinator,
        device_info: PowerviewDeviceInfo,
        room_name: str,
        shade: BaseShade,
        name: str,
        description: PowerviewNumberDescription,
    ) -> None:
        """Initialize the number entity."""
        super().__init__(coordinator, device_info, room_name, shade, name)
        self.entity_description = description
        self._attr_unique_id = f"{self._attr_unique_id}_{description.key}"

    def set_native_value(self, value: float) -> None:
        """Update the current value."""
        self._attr_native_value = value
        self.entity_description.store_value_fn(self.coordinator, self._shade.id, value)
        self.async_write_ha_state()

    async def async_added_to_hass(self) -> None:
        """Restore last state."""
        await super().async_added_to_hass()
        last_number_data = await self.async_get_last_number_data()
        value = last_number_data.native_value if last_number_data is not None else 0
        self._attr_native_value = value
        self.entity_description.store_value_fn(self.coordinator, self._shade.id, value)
