"""Support for EverLights lights."""

from datetime import timedelta
import logging
from typing import Any, cast, override

import pyeverlights
import voluptuous as vol

from homeassistant.components.light import (
    ATTR_BRIGHTNESS,
    ATTR_EFFECT,
    ATTR_HS_COLOR,
    PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
    ColorMode,
    LightEntity,
    LightEntityFeature,
)
from homeassistant.const import CONF_HOSTS
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import color as color_util

_LOGGER = logging.getLogger(__name__)

SCAN_INTERVAL = timedelta(minutes=1)

PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
    {vol.Required(CONF_HOSTS): vol.All(cv.ensure_list, [cv.string])}
)


def color_rgb_to_int(red: int, green: int, blue: int) -> int:
    """Return a RGB color as an integer."""
    return red * 256 * 256 + green * 256 + blue


def color_int_to_rgb(value: int) -> tuple[int, int, int]:
    """Return an RGB tuple from an integer."""
    return (value >> 16, (value >> 8) & 0xFF, value & 0xFF)


async def async_setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up the EverLights lights from configuration.yaml."""
    lights = []

    for ipaddr in config[CONF_HOSTS]:
        api = pyeverlights.EverLights(ipaddr, async_get_clientsession(hass))

        try:
            status = await api.get_status()

            effects = await api.get_all_patterns()

        except pyeverlights.ConnectionError as err:
            raise PlatformNotReady from err

        lights.append(EverLightsLight(api, pyeverlights.ZONE_1, status, effects))
        lights.append(EverLightsLight(api, pyeverlights.ZONE_2, status, effects))

    async_add_entities(lights)


class EverLightsLight(LightEntity):
    """Representation of a Flux light."""

    _attr_color_mode = ColorMode.HS
    _attr_supported_color_modes = {ColorMode.HS}
    _attr_supported_features = LightEntityFeature.EFFECT

    def __init__(
        self,
        api: pyeverlights.EverLights,
        channel: int,
        status: dict[str, Any],
        effects: list[str],
    ) -> None:
        """Initialize the light."""
        self._api = api
        self._channel = channel
        self._status = status
        self._attr_effect_list = effects
        self._mac = status["mac"]
        self._error_reported = False
        self._attr_hs_color = (255, 255)
        self._attr_brightness = 255

        self._attr_name = f"EverLights {self._mac} Zone {self._channel}"
        self._attr_unique_id = f"{self._mac}-{self._channel}"

    @property
    @override
    def is_on(self) -> bool:
        """Return true if device is on."""
        return self._status[f"ch{self._channel}Active"] == 1

    @override
    async def async_turn_on(self, **kwargs: Any) -> None:
        """Turn the light on."""
        hs_color = cast(
            tuple[float, float], kwargs.get(ATTR_HS_COLOR, self._attr_hs_color)
        )
        brightness = cast(int, kwargs.get(ATTR_BRIGHTNESS, self._attr_brightness))
        effect = kwargs.get(ATTR_EFFECT)

        if effect is not None:
            colors = await self._api.set_pattern_by_id(self._channel, effect)

            rgb = color_int_to_rgb(colors[0])
            hsv = color_util.color_RGB_to_hsv(*rgb)
            hs_color = hsv[:2]
            brightness = round(hsv[2] / 100 * 255)

        else:
            rgb = color_util.color_hsv_to_RGB(
                hs_color[0], hs_color[1], brightness / 255 * 100
            )
            colors = [color_rgb_to_int(*rgb)]

            await self._api.set_pattern(self._channel, colors)

        self._attr_hs_color = hs_color
        self._attr_brightness = brightness
        self._attr_effect = effect

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

    async def async_update(self) -> None:
        """Synchronize state with control box."""
        try:
            self._status = await self._api.get_status()
        except pyeverlights.ConnectionError:
            if self.available:
                _LOGGER.warning("EverLights control box connection lost")
            self._attr_available = False
        else:
            if not self.available:
                _LOGGER.warning("EverLights control box connection restored")
            self._attr_available = True
