"""Fully Kiosk Browser switch."""

from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass
from typing import Any

from fullykiosk import FullyKiosk

from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import DOMAIN
from .coordinator import FullyKioskDataUpdateCoordinator
from .entity import FullyKioskEntity


@dataclass(frozen=True, kw_only=True)
class FullySwitchEntityDescription(SwitchEntityDescription):
    """Fully Kiosk Browser switch entity description."""

    on_action: Callable[[FullyKiosk], Any]
    off_action: Callable[[FullyKiosk], Any]
    is_on_fn: Callable[[dict[str, Any]], Any]
    mqtt_on_event: str | None
    mqtt_off_event: str | None


SWITCHES: tuple[FullySwitchEntityDescription, ...] = (
    FullySwitchEntityDescription(
        key="screensaver",
        translation_key="screensaver",
        on_action=lambda fully: fully.startScreensaver(),
        off_action=lambda fully: fully.stopScreensaver(),
        is_on_fn=lambda data: data.get("isInScreensaver"),
        mqtt_on_event="onScreensaverStart",
        mqtt_off_event="onScreensaverStop",
    ),
    FullySwitchEntityDescription(
        key="maintenance",
        translation_key="maintenance",
        entity_category=EntityCategory.CONFIG,
        on_action=lambda fully: fully.enableLockedMode(),
        off_action=lambda fully: fully.disableLockedMode(),
        is_on_fn=lambda data: data.get("maintenanceMode"),
        mqtt_on_event=None,
        mqtt_off_event=None,
    ),
    FullySwitchEntityDescription(
        key="kiosk",
        translation_key="kiosk",
        entity_category=EntityCategory.CONFIG,
        on_action=lambda fully: fully.lockKiosk(),
        off_action=lambda fully: fully.unlockKiosk(),
        is_on_fn=lambda data: data.get("kioskLocked"),
        mqtt_on_event=None,
        mqtt_off_event=None,
    ),
    FullySwitchEntityDescription(
        key="motion-detection",
        translation_key="motion_detection",
        entity_category=EntityCategory.CONFIG,
        on_action=lambda fully: fully.enableMotionDetection(),
        off_action=lambda fully: fully.disableMotionDetection(),
        is_on_fn=lambda data: data["settings"].get("motionDetection"),
        mqtt_on_event=None,
        mqtt_off_event=None,
    ),
    FullySwitchEntityDescription(
        key="screenOn",
        translation_key="screen_on",
        on_action=lambda fully: fully.screenOn(),
        off_action=lambda fully: fully.screenOff(),
        is_on_fn=lambda data: data.get("screenOn"),
        mqtt_on_event="screenOn",
        mqtt_off_event="screenOff",
    ),
)


async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: ConfigEntry,
    async_add_entities: AddEntitiesCallback,
) -> None:
    """Set up the Fully Kiosk Browser switch."""
    coordinator: FullyKioskDataUpdateCoordinator = hass.data[DOMAIN][
        config_entry.entry_id
    ]

    async_add_entities(
        FullySwitchEntity(coordinator, description) for description in SWITCHES
    )


class FullySwitchEntity(FullyKioskEntity, SwitchEntity):
    """Fully Kiosk Browser switch entity."""

    entity_description: FullySwitchEntityDescription

    def __init__(
        self,
        coordinator: FullyKioskDataUpdateCoordinator,
        description: FullySwitchEntityDescription,
    ) -> None:
        """Initialize the Fully Kiosk Browser switch entity."""
        super().__init__(coordinator)
        self.entity_description = description
        self._attr_unique_id = f"{coordinator.data['deviceID']}-{description.key}"
        self._turned_on_subscription: CALLBACK_TYPE | None = None
        self._turned_off_subscription: CALLBACK_TYPE | None = None

    async def async_added_to_hass(self) -> None:
        """When entity is added to hass."""
        await super().async_added_to_hass()
        description = self.entity_description
        self._turned_on_subscription = await self.mqtt_subscribe(
            description.mqtt_off_event, self._turn_off
        )
        self._turned_off_subscription = await self.mqtt_subscribe(
            description.mqtt_on_event, self._turn_on
        )

    async def async_will_remove_from_hass(self) -> None:
        """Close MQTT subscriptions when removed."""
        await super().async_will_remove_from_hass()
        if self._turned_off_subscription is not None:
            self._turned_off_subscription()
        if self._turned_on_subscription is not None:
            self._turned_on_subscription()

    async def async_turn_on(self, **kwargs: Any) -> None:
        """Turn the entity on."""
        await self.entity_description.on_action(self.coordinator.fully)
        await self.coordinator.async_refresh()

    async def async_turn_off(self, **kwargs: Any) -> None:
        """Turn the entity off."""
        await self.entity_description.off_action(self.coordinator.fully)
        await self.coordinator.async_refresh()

    def _turn_off(self, **kwargs: Any) -> None:
        """Optimistically turn off."""
        self._attr_is_on = False
        self.async_write_ha_state()

    def _turn_on(self, **kwargs: Any) -> None:
        """Optimistically turn on."""
        self._attr_is_on = True
        self.async_write_ha_state()

    @callback
    def _handle_coordinator_update(self) -> None:
        """Handle updated data from the coordinator."""
        self._attr_is_on = bool(self.entity_description.is_on_fn(self.coordinator.data))
        self.async_write_ha_state()
