"""Support for HomematicIP Cloud lock devices."""

import logging
from typing import Any, override

from homematicip.base.enums import LockState, MotorState
from homematicip.device import DoorLockDrive

from homeassistant.components.lock import LockEntity, LockEntityFeature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .entity import HomematicipGenericEntity
from .hap import HomematicIPConfigEntry, HomematicipHAP
from .helpers import handle_errors

_LOGGER = logging.getLogger(__name__)

ATTR_AUTO_RELOCK_DELAY = "auto_relock_delay"
ATTR_DOOR_HANDLE_TYPE = "door_handle_type"
ATTR_DOOR_LOCK_DIRECTION = "door_lock_direction"
ATTR_DOOR_LOCK_NEUTRAL_POSITION = "door_lock_neutral_position"
ATTR_DOOR_LOCK_TURNS = "door_lock_turns"

DEVICE_DLD_ATTRIBUTES = {
    "autoRelockDelay": ATTR_AUTO_RELOCK_DELAY,
    "doorHandleType": ATTR_DOOR_HANDLE_TYPE,
    "doorLockDirection": ATTR_DOOR_LOCK_DIRECTION,
    "doorLockNeutralPosition": ATTR_DOOR_LOCK_NEUTRAL_POSITION,
    "doorLockTurns": ATTR_DOOR_LOCK_TURNS,
}


async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: HomematicIPConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up the HomematicIP locks from a config entry."""
    hap = config_entry.runtime_data

    async_add_entities(
        HomematicipDoorLockDrive(hap, device)
        for device in hap.home.devices
        if isinstance(device, DoorLockDrive)
    )


class HomematicipDoorLockDrive(HomematicipGenericEntity, LockEntity):
    """Representation of the HomematicIP DoorLockDrive."""

    _attr_supported_features = LockEntityFeature.OPEN

    def __init__(self, hap: HomematicipHAP, device: DoorLockDrive) -> None:
        """Initialize the door lock drive."""
        super().__init__(hap, device, feature_id="lock")

    @property
    @override
    def is_locked(self) -> bool | None:
        """Return true if device is locked."""
        return (
            self._device.lockState == LockState.LOCKED
            and self._device.motorState == MotorState.STOPPED
        )

    @property
    @override
    def is_locking(self) -> bool:
        """Return true if device is locking."""
        return self._device.motorState == MotorState.CLOSING

    @property
    @override
    def is_unlocking(self) -> bool:
        """Return true if device is unlocking."""
        return self._device.motorState == MotorState.OPENING

    @handle_errors
    @override
    async def async_lock(self, **kwargs: Any) -> None:
        """Lock the device."""
        return await self._device.set_lock_state_async(LockState.LOCKED)

    @handle_errors
    @override
    async def async_unlock(self, **kwargs: Any) -> None:
        """Unlock the device."""
        return await self._device.set_lock_state_async(LockState.UNLOCKED)

    @handle_errors
    @override
    async def async_open(self, **kwargs: Any) -> None:
        """Open the door latch."""
        return await self._device.set_lock_state_async(LockState.OPEN)

    @property
    @override
    def extra_state_attributes(self) -> dict[str, Any]:
        """Return the state attributes of the device."""
        return super().extra_state_attributes | {
            attr_key: attr_value
            for attr, attr_key in DEVICE_DLD_ATTRIBUTES.items()
            if (attr_value := getattr(self._device, attr, None)) is not None
        }
