"""Support for SwitchBee light."""

from typing import Any, cast, override

from switchbee.api.central_unit import SwitchBeeDeviceOfflineError, SwitchBeeError
from switchbee.device import ApiStateCommand, DeviceType, SwitchBeeDimmer

from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .coordinator import SwitchBeeConfigEntry, SwitchBeeCoordinator
from .entity import SwitchBeeDeviceEntity

MAX_BRIGHTNESS = 255


def _hass_brightness_to_switchbee(value: int) -> int:
    """Convert hass brightness to SwitchBee."""
    sb_brightness = int(100 * value / MAX_BRIGHTNESS)
    # SwitchBee maximum brightness is 99
    return sb_brightness if sb_brightness != 100 else 99


def _switchbee_brightness_to_hass(value: int) -> int:
    """Convert SwitchBee brightness to hass."""
    if value == 99:
        value = 100
    return round(value * MAX_BRIGHTNESS / 100)


async def async_setup_entry(
    hass: HomeAssistant,
    entry: SwitchBeeConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up SwitchBee light."""
    coordinator = entry.runtime_data
    async_add_entities(
        SwitchBeeLightEntity(cast(SwitchBeeDimmer, switchbee_device), coordinator)
        for switchbee_device in coordinator.data.values()
        if switchbee_device.type is DeviceType.Dimmer
    )


class SwitchBeeLightEntity(SwitchBeeDeviceEntity[SwitchBeeDimmer], LightEntity):
    """Representation of a SwitchBee light."""

    _attr_color_mode = ColorMode.BRIGHTNESS
    _attr_supported_color_modes = {ColorMode.BRIGHTNESS}

    def __init__(
        self,
        device: SwitchBeeDimmer,
        coordinator: SwitchBeeCoordinator,
    ) -> None:
        """Initialize the SwitchBee light."""
        super().__init__(device, coordinator)
        self._attr_is_on = False
        self._attr_brightness = 0

        self._update_attrs_from_coordinator()

    @callback
    @override
    def _handle_coordinator_update(self) -> None:
        """Handle updated data from the coordinator."""
        self._update_attrs_from_coordinator()
        super()._handle_coordinator_update()

    def _update_attrs_from_coordinator(self) -> None:
        coordinator_device = self._get_coordinator_device()
        brightness = coordinator_device.brightness

        # module is offline
        if brightness == -1:
            self._check_if_became_offline()
            return

        self._check_if_became_online()

        self._attr_is_on = bool(brightness != 0)

        # 1-99 is the only valid SwitchBee brightness range
        if 0 < brightness < 100:
            self._attr_brightness = _switchbee_brightness_to_hass(brightness)

    @override
    async def async_turn_on(self, **kwargs: Any) -> None:
        """Async function to set on to light."""
        if ATTR_BRIGHTNESS in kwargs:
            state: int | str = _hass_brightness_to_switchbee(kwargs[ATTR_BRIGHTNESS])
        else:
            state = ApiStateCommand.ON
            if self.brightness:
                state = _hass_brightness_to_switchbee(self.brightness)

        try:
            await self.coordinator.api.set_state(self._device.id, state)
        except (SwitchBeeError, SwitchBeeDeviceOfflineError) as exp:
            raise HomeAssistantError(
                f"Failed to set {self.name} state {state}, {exp!s}"
            ) from exp

        if not isinstance(state, int):
            # We just turned the light on, still don't know the last brightness
            # known the Central Unit (yet) the brightness will be learned
            # and updated in the next coordinator refresh
            return

        # update the coordinator data manually we already know the Central Unit
        # brightness data for this light
        self._get_coordinator_device().brightness = state
        self.coordinator.async_set_updated_data(self.coordinator.data)

    @override
    async def async_turn_off(self, **kwargs: Any) -> None:
        """Turn off SwitchBee light."""
        try:
            await self.coordinator.api.set_state(self._device.id, ApiStateCommand.OFF)
        except (SwitchBeeError, SwitchBeeDeviceOfflineError) as exp:
            raise HomeAssistantError(
                f"Failed to turn off {self._attr_name}, {exp!s}"
            ) from exp

        # update the coordinator manually
        self._get_coordinator_device().brightness = 0
        self.coordinator.async_set_updated_data(self.coordinator.data)
