"""Platform for Miele light entity."""

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

from aiohttp import ClientResponseError

from homeassistant.components.light import (
    ColorMode,
    LightEntity,
    LightEntityDescription,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType

from .const import AMBIENT_LIGHT, DOMAIN, LIGHT, LIGHT_OFF, LIGHT_ON, MieleAppliance
from .coordinator import MieleConfigEntry
from .entity import MieleDevice, MieleEntity

PARALLEL_UPDATES = 1

_LOGGER = logging.getLogger(__name__)


@dataclass(frozen=True, kw_only=True)
class MieleLightDescription(LightEntityDescription):
    """Class describing Miele light entities."""

    value_fn: Callable[[MieleDevice], StateType]
    light_type: str


@dataclass
class MieleLightDefinition:
    """Class for defining light entities."""

    types: tuple[MieleAppliance, ...]
    description: MieleLightDescription


LIGHT_TYPES: Final[tuple[MieleLightDefinition, ...]] = (
    MieleLightDefinition(
        types=(
            MieleAppliance.OVEN,
            MieleAppliance.OVEN_MICROWAVE,
            MieleAppliance.STEAM_OVEN,
            MieleAppliance.MICROWAVE,
            MieleAppliance.COFFEE_SYSTEM,
            MieleAppliance.HOOD,
            MieleAppliance.STEAM_OVEN_COMBI,
            MieleAppliance.WINE_CABINET,
            MieleAppliance.WINE_CONDITIONING_UNIT,
            MieleAppliance.WINE_STORAGE_CONDITIONING_UNIT,
            MieleAppliance.STEAM_OVEN_MICRO,
            MieleAppliance.WINE_CABINET_FREEZER,
            MieleAppliance.STEAM_OVEN_MK2,
        ),
        description=MieleLightDescription(
            key="light",
            value_fn=lambda value: value.state_light,
            light_type=LIGHT,
            translation_key="light",
        ),
    ),
    MieleLightDefinition(
        types=(MieleAppliance.HOOD,),
        description=MieleLightDescription(
            key="ambient_light",
            value_fn=lambda value: value.state_ambient_light,
            light_type=AMBIENT_LIGHT,
            translation_key="ambient_light",
        ),
    ),
)


async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: MieleConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up the light platform."""
    coordinator = config_entry.runtime_data.coordinator
    added_devices: set[str] = set()

    def _async_add_new_devices() -> None:
        nonlocal added_devices
        new_devices_set, current_devices = coordinator.async_add_devices(added_devices)
        added_devices = current_devices

        async_add_entities(
            MieleLight(coordinator, device_id, definition.description)
            for device_id, device in coordinator.data.devices.items()
            for definition in LIGHT_TYPES
            if device_id in new_devices_set and device.device_type in definition.types
        )

    config_entry.async_on_unload(coordinator.async_add_listener(_async_add_new_devices))
    _async_add_new_devices()


class MieleLight(MieleEntity, LightEntity):
    """Representation of a Light."""

    entity_description: MieleLightDescription
    _attr_color_mode = ColorMode.ONOFF
    _attr_supported_color_modes = {ColorMode.ONOFF}

    @property
    @override
    def is_on(self) -> bool:
        """Return current on/off state."""
        return self.entity_description.value_fn(self.device) == LIGHT_ON

    @override
    async def async_turn_on(self, **kwargs: Any) -> None:
        """Turn on the light."""
        await self.async_turn_light(LIGHT_ON)

    @override
    async def async_turn_off(self, **kwargs: Any) -> None:
        """Turn the light off."""
        await self.async_turn_light(LIGHT_OFF)

    async def async_turn_light(self, mode: int) -> None:
        """Set light to mode."""
        try:
            await self.api.send_action(
                self._device_id, {self.entity_description.light_type: mode}
            )
        except ClientResponseError as err:
            _LOGGER.debug("Error setting light state for %s: %s", self.entity_id, err)
            raise HomeAssistantError(
                translation_domain=DOMAIN,
                translation_key="set_state_error",
                translation_placeholders={
                    "entity": self.entity_id,
                },
            ) from err
