"""Sensors definition for SWS12500."""

import logging

from homeassistant.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo, generate_entity_id
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from . import WeatherDataUpdateCoordinator
from .const import (
    BATTERY_LIST,
    CHILL_INDEX,
    DOMAIN,
    HEAT_INDEX,
    OUTSIDE_HUMIDITY,
    OUTSIDE_TEMP,
    SENSORS_TO_LOAD,
    WIND_AZIMUT,
    WIND_DIR,
    WIND_SPEED,
    WSLINK,
    UnitOfBat,
)
from .sensors_common import WeatherSensorEntityDescription
from .sensors_weather import SENSOR_TYPES_WEATHER_API
from .sensors_wslink import SENSOR_TYPES_WSLINK
from .utils import battery_level_to_icon, battery_level_to_text, chill_index, heat_index

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: ConfigEntry,
    async_add_entities: AddEntitiesCallback,
) -> None:
    """Set up Weather Station sensors."""

    coordinator: WeatherDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]

    sensors_to_load: list = []
    sensors: list = []
    _wslink = config_entry.options.get(WSLINK)

    SENSOR_TYPES = SENSOR_TYPES_WSLINK if _wslink else SENSOR_TYPES_WEATHER_API

    # Check if we have some sensors to load.
    if sensors_to_load := config_entry.options.get(SENSORS_TO_LOAD, []):
        if WIND_DIR in sensors_to_load:
            sensors_to_load.append(WIND_AZIMUT)
        if (OUTSIDE_HUMIDITY in sensors_to_load) and (OUTSIDE_TEMP in sensors_to_load):
            sensors_to_load.append(HEAT_INDEX)

        if (WIND_SPEED in sensors_to_load) and (OUTSIDE_TEMP in sensors_to_load):
            sensors_to_load.append(CHILL_INDEX)
        sensors = [
            WeatherSensor(hass, description, coordinator)
            for description in SENSOR_TYPES
            if description.key in sensors_to_load
        ]
        async_add_entities(sensors)


class WeatherSensor(  # pyright: ignore[reportIncompatibleVariableOverride]
    CoordinatorEntity[WeatherDataUpdateCoordinator], SensorEntity
):  # pyright: ignore[reportIncompatibleVariableOverride]
    """Implementation of Weather Sensor entity."""

    _attr_has_entity_name = True
    _attr_should_poll = False

    def __init__(
        self,
        hass: HomeAssistant,
        description: WeatherSensorEntityDescription,
        coordinator: WeatherDataUpdateCoordinator,
    ) -> None:
        """Initialize sensor."""
        super().__init__(coordinator)
        self.hass = hass
        self.coordinator = coordinator
        self.entity_description = description
        self._attr_unique_id = description.key
        self._data = None

    async def async_added_to_hass(self) -> None:
        """Handle listeners to reloaded sensors."""

        await super().async_added_to_hass()

        self.coordinator.async_add_listener(self._handle_coordinator_update)

    @callback
    def _handle_coordinator_update(self) -> None:
        """Handle updated data from the coordinator."""
        self._data = self.coordinator.data.get(self.entity_description.key)

        super()._handle_coordinator_update()

        self.async_write_ha_state()

    @property
    def native_value(self):  # pyright: ignore[reportIncompatibleVariableOverride]
        """Return value of entity."""

        _wslink = self.coordinator.config.options.get(WSLINK)

        if self.coordinator.data and (WIND_AZIMUT in self.entity_description.key):
            return self.entity_description.value_fn(self.coordinator.data.get(WIND_DIR))  # pyright: ignore[ reportAttributeAccessIssue]

        if (
            self.coordinator.data
            and (HEAT_INDEX in self.entity_description.key)
            and not _wslink
        ):
            return self.entity_description.value_fn(heat_index(self.coordinator.data))  # pyright: ignore[ reportAttributeAccessIssue]

        if (
            self.coordinator.data
            and (CHILL_INDEX in self.entity_description.key)
            and not _wslink
        ):
            return self.entity_description.value_fn(chill_index(self.coordinator.data))  # pyright: ignore[ reportAttributeAccessIssue]

        return (
            None if self._data == "" else self.entity_description.value_fn(self._data)  # pyright: ignore[ reportAttributeAccessIssue]
        )

    @property
    def suggested_entity_id(self) -> str:
        """Return name."""
        return generate_entity_id("sensor.{}", self.entity_description.key)

    @property
    def icon(self) -> str | None:  # pyright: ignore[reportIncompatibleVariableOverride]
        """Return the dynamic icon for battery representation."""

        if self.entity_description.key in BATTERY_LIST:
            if self.native_value:
                battery_level = battery_level_to_text(self.native_value)
                return battery_level_to_icon(battery_level)

            return battery_level_to_icon(UnitOfBat.UNKNOWN)

        return self.entity_description.icon

    @property
    def device_info(self) -> DeviceInfo:  # pyright: ignore[reportIncompatibleVariableOverride]
        """Device info."""
        return DeviceInfo(
            connections=set(),
            name="Weather Station SWS 12500",
            entry_type=DeviceEntryType.SERVICE,
            identifiers={(DOMAIN,)},  # type: ignore[arg-type]
            manufacturer="Schizza",
            model="Weather Station SWS 12500",
        )
