"""Base classes for SmartTub entities."""

from typing import Any

from smarttub import Spa, SpaSensor, SpaState

from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import (
    CoordinatorEntity,
    DataUpdateCoordinator,
)

from .const import ATTR_SENSORS, DOMAIN
from .helpers import get_spa_name


class SmartTubEntity(CoordinatorEntity):
    """Base class for SmartTub entities."""

    _attr_has_entity_name = True

    def __init__(
        self,
        coordinator: DataUpdateCoordinator[dict[str, Any]],
        spa: Spa,
        entity_name: str,
    ) -> None:
        """Initialize the entity.

        Given a spa id and a short name for the entity, we provide basic device
        info, name, unique id, etc. for all derived entities.
        """

        super().__init__(coordinator)
        self.spa = spa
        self._attr_unique_id = f"{spa.id}-{entity_name}"
        self._attr_device_info = DeviceInfo(
            identifiers={(DOMAIN, spa.id)},
            manufacturer=spa.brand,
            model=spa.model,
            name=get_spa_name(spa),
        )

    @property
    def spa_status(self) -> SpaState:
        """Retrieve the result of Spa.get_status()."""

        return self.coordinator.data[self.spa.id].get("status")


class SmartTubOnboardSensorBase(SmartTubEntity):
    """Base class for SmartTub onboard sensors."""

    def __init__(
        self,
        coordinator: DataUpdateCoordinator[dict[str, Any]],
        spa: Spa,
        sensor_name: str,
        state_key: str,
    ) -> None:
        """Initialize the entity."""
        super().__init__(coordinator, spa, sensor_name)
        self._state_key = state_key

    @property
    def _state(self):
        """Retrieve the underlying state from the spa."""
        return getattr(self.spa_status, self._state_key)


class SmartTubExternalSensorBase(SmartTubEntity):
    """Class for additional BLE wireless sensors sold separately."""

    _attr_translation_key = "external_sensor"

    def __init__(
        self,
        coordinator: DataUpdateCoordinator[dict[str, Any]],
        spa: Spa,
        sensor: SpaSensor,
    ) -> None:
        """Initialize the external sensor entity."""
        super().__init__(coordinator, spa, self._sensor_key(sensor))
        self.sensor_address = sensor.address
        self._attr_unique_id = f"{spa.id}-externalsensor-{sensor.address}"
        self._attr_translation_placeholders = {
            "sensor_name": self._human_readable_name(sensor),
        }

    @staticmethod
    def _sensor_key(sensor: SpaSensor) -> str:
        """Return a key for the sensor suitable for unique_id generation."""
        return sensor.name.strip("{}").replace("-", "_")

    @staticmethod
    def _human_readable_name(sensor: SpaSensor) -> str:
        """Return a human-readable name for the sensor."""
        return " ".join(
            word.capitalize() for word in sensor.name.strip("{}").split("-")
        )

    @property
    def sensor(self) -> SpaSensor:
        """Access the smarttub.SpaSensor instance for this sensor."""
        return self.coordinator.data[self.spa.id][ATTR_SENSORS][self.sensor_address]
