"""The Homee alarm control panel platform."""

from dataclasses import dataclass
from typing import override

from pyHomee.const import AttributeChangedBy, AttributeType
from pyHomee.model import HomeeAttribute, HomeeNode

from homeassistant.components.alarm_control_panel import (
    AlarmControlPanelEntity,
    AlarmControlPanelEntityDescription,
    AlarmControlPanelEntityFeature,
    AlarmControlPanelState,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from . import DOMAIN, HomeeConfigEntry
from .entity import HomeeEntity
from .helpers import get_name_for_enum, setup_homee_platform

PARALLEL_UPDATES = 0


@dataclass(frozen=True, kw_only=True)
class HomeeAlarmControlPanelEntityDescription(AlarmControlPanelEntityDescription):
    """A class that describes Homee alarm control panel entities."""

    code_arm_required: bool = False
    state_list: list[AlarmControlPanelState]


ALARM_DESCRIPTIONS = {
    AttributeType.HOMEE_MODE: HomeeAlarmControlPanelEntityDescription(
        key="homee_mode",
        state_list=[
            AlarmControlPanelState.ARMED_HOME,
            AlarmControlPanelState.ARMED_NIGHT,
            AlarmControlPanelState.ARMED_AWAY,
            AlarmControlPanelState.ARMED_VACATION,
        ],
    )
}


def get_supported_features(
    state_list: list[AlarmControlPanelState],
) -> AlarmControlPanelEntityFeature:
    """Return supported features based on the state list."""
    supported_features = AlarmControlPanelEntityFeature(0)
    if AlarmControlPanelState.ARMED_HOME in state_list:
        supported_features |= AlarmControlPanelEntityFeature.ARM_HOME
    if AlarmControlPanelState.ARMED_AWAY in state_list:
        supported_features |= AlarmControlPanelEntityFeature.ARM_AWAY
    if AlarmControlPanelState.ARMED_NIGHT in state_list:
        supported_features |= AlarmControlPanelEntityFeature.ARM_NIGHT
    if AlarmControlPanelState.ARMED_VACATION in state_list:
        supported_features |= AlarmControlPanelEntityFeature.ARM_VACATION
    return supported_features


async def add_alarm_control_panel_entities(
    hass: HomeAssistant,
    config_entry: HomeeConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
    nodes: list[HomeeNode],
) -> None:
    """Add homee alarm control panel entities."""
    async_add_entities(
        HomeeAlarmPanel(
            hass, attribute, config_entry, ALARM_DESCRIPTIONS[attribute.type]
        )
        for node in nodes
        for attribute in node.attributes
        if attribute.type in ALARM_DESCRIPTIONS and attribute.editable
    )


async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: HomeeConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Add the homee platform for the alarm control panel component."""

    await setup_homee_platform(
        hass, add_alarm_control_panel_entities, async_add_entities, config_entry
    )


class HomeeAlarmPanel(HomeeEntity, AlarmControlPanelEntity):
    """Representation of a Homee alarm control panel."""

    entity_description: HomeeAlarmControlPanelEntityDescription

    def __init__(
        self,
        hass: HomeAssistant,
        attribute: HomeeAttribute,
        entry: HomeeConfigEntry,
        description: HomeeAlarmControlPanelEntityDescription,
    ) -> None:
        """Initialize a Homee alarm control panel entity."""
        super().__init__(hass, attribute, entry)
        self.entity_description = description
        self._attr_code_arm_required = description.code_arm_required
        self._attr_supported_features = get_supported_features(description.state_list)
        self._attr_translation_key = description.key

    @property
    @override
    def alarm_state(self) -> AlarmControlPanelState:
        """Return current state."""
        return self.entity_description.state_list[int(self._attribute.current_value)]

    @property
    @override
    def changed_by(self) -> str:
        """Return by whom or what the entity was last changed."""
        changed_by_name = get_name_for_enum(
            AttributeChangedBy, self._attribute.changed_by
        )
        return f"{changed_by_name} - {self._attribute.changed_by_id}"

    async def _async_set_alarm_state(self, state: AlarmControlPanelState) -> None:
        """Set the alarm state."""
        if state in self.entity_description.state_list:
            await self.async_set_homee_value(
                self.entity_description.state_list.index(state)
            )

    @override
    async def async_alarm_disarm(self, code: str | None = None) -> None:
        """Send disarm command."""
        # Since disarm is always present in the UI, we raise an error.
        raise ServiceValidationError(
            translation_domain=DOMAIN,
            translation_key="disarm_not_supported",
        )

    @override
    async def async_alarm_arm_home(self, code: str | None = None) -> None:
        """Send arm home command."""
        await self._async_set_alarm_state(AlarmControlPanelState.ARMED_HOME)

    @override
    async def async_alarm_arm_night(self, code: str | None = None) -> None:
        """Send arm night command."""
        await self._async_set_alarm_state(AlarmControlPanelState.ARMED_NIGHT)

    @override
    async def async_alarm_arm_away(self, code: str | None = None) -> None:
        """Send arm away command."""
        await self._async_set_alarm_state(AlarmControlPanelState.ARMED_AWAY)

    @override
    async def async_alarm_arm_vacation(self, code: str | None = None) -> None:
        """Send arm vacation command."""
        await self._async_set_alarm_state(AlarmControlPanelState.ARMED_VACATION)
