"""Climate platform for Actron Air integration."""

from typing import Any

from actron_neo_api import ActronAirNeoStatus, ActronAirNeoZone

from homeassistant.components.climate import (
    FAN_AUTO,
    FAN_HIGH,
    FAN_LOW,
    FAN_MEDIUM,
    ClimateEntity,
    ClimateEntityFeature,
    HVACMode,
)
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN
from .coordinator import ActronAirConfigEntry, ActronAirSystemCoordinator

PARALLEL_UPDATES = 0

FAN_MODE_MAPPING_ACTRONAIR_TO_HA = {
    "AUTO": FAN_AUTO,
    "LOW": FAN_LOW,
    "MED": FAN_MEDIUM,
    "HIGH": FAN_HIGH,
}
FAN_MODE_MAPPING_HA_TO_ACTRONAIR = {
    v: k for k, v in FAN_MODE_MAPPING_ACTRONAIR_TO_HA.items()
}
HVAC_MODE_MAPPING_ACTRONAIR_TO_HA = {
    "COOL": HVACMode.COOL,
    "HEAT": HVACMode.HEAT,
    "FAN": HVACMode.FAN_ONLY,
    "AUTO": HVACMode.AUTO,
    "OFF": HVACMode.OFF,
}
HVAC_MODE_MAPPING_HA_TO_ACTRONAIR = {
    v: k for k, v in HVAC_MODE_MAPPING_ACTRONAIR_TO_HA.items()
}


async def async_setup_entry(
    hass: HomeAssistant,
    entry: ActronAirConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up Actron Air climate entities."""
    system_coordinators = entry.runtime_data.system_coordinators
    entities: list[ClimateEntity] = []

    for coordinator in system_coordinators.values():
        status = coordinator.data
        name = status.ac_system.system_name
        entities.append(ActronSystemClimate(coordinator, name))

        entities.extend(
            ActronZoneClimate(coordinator, zone)
            for zone in status.remote_zone_info
            if zone.exists
        )

    async_add_entities(entities)


class BaseClimateEntity(CoordinatorEntity[ActronAirSystemCoordinator], ClimateEntity):
    """Base class for Actron Air climate entities."""

    _attr_has_entity_name = True
    _attr_temperature_unit = UnitOfTemperature.CELSIUS
    _attr_supported_features = (
        ClimateEntityFeature.TARGET_TEMPERATURE
        | ClimateEntityFeature.FAN_MODE
        | ClimateEntityFeature.TURN_ON
        | ClimateEntityFeature.TURN_OFF
    )
    _attr_name = None
    _attr_fan_modes = list(FAN_MODE_MAPPING_ACTRONAIR_TO_HA.values())
    _attr_hvac_modes = list(HVAC_MODE_MAPPING_ACTRONAIR_TO_HA.values())

    def __init__(
        self,
        coordinator: ActronAirSystemCoordinator,
        name: str,
    ) -> None:
        """Initialize an Actron Air unit."""
        super().__init__(coordinator)
        self._serial_number = coordinator.serial_number


class ActronSystemClimate(BaseClimateEntity):
    """Representation of the Actron Air system."""

    _attr_supported_features = (
        ClimateEntityFeature.TARGET_TEMPERATURE
        | ClimateEntityFeature.FAN_MODE
        | ClimateEntityFeature.TURN_ON
        | ClimateEntityFeature.TURN_OFF
    )

    def __init__(
        self,
        coordinator: ActronAirSystemCoordinator,
        name: str,
    ) -> None:
        """Initialize an Actron Air unit."""
        super().__init__(coordinator, name)
        serial_number = coordinator.serial_number
        self._attr_unique_id = serial_number
        self._attr_device_info = DeviceInfo(
            identifiers={(DOMAIN, serial_number)},
            name=self._status.ac_system.system_name,
            manufacturer="Actron Air",
            model_id=self._status.ac_system.master_wc_model,
            sw_version=self._status.ac_system.master_wc_firmware_version,
            serial_number=serial_number,
        )

    @property
    def min_temp(self) -> float:
        """Return the minimum temperature that can be set."""
        return self._status.min_temp

    @property
    def max_temp(self) -> float:
        """Return the maximum temperature that can be set."""
        return self._status.max_temp

    @property
    def _status(self) -> ActronAirNeoStatus:
        """Get the current status from the coordinator."""
        return self.coordinator.data

    @property
    def hvac_mode(self) -> HVACMode | None:
        """Return the current HVAC mode."""
        if not self._status.user_aircon_settings.is_on:
            return HVACMode.OFF

        mode = self._status.user_aircon_settings.mode
        return HVAC_MODE_MAPPING_ACTRONAIR_TO_HA.get(mode)

    @property
    def fan_mode(self) -> str | None:
        """Return the current fan mode."""
        fan_mode = self._status.user_aircon_settings.fan_mode
        return FAN_MODE_MAPPING_ACTRONAIR_TO_HA.get(fan_mode)

    @property
    def current_humidity(self) -> float:
        """Return the current humidity."""
        return self._status.master_info.live_humidity_pc

    @property
    def current_temperature(self) -> float:
        """Return the current temperature."""
        return self._status.master_info.live_temp_c

    @property
    def target_temperature(self) -> float:
        """Return the target temperature."""
        return self._status.user_aircon_settings.temperature_setpoint_cool_c

    async def async_set_fan_mode(self, fan_mode: str) -> None:
        """Set a new fan mode."""
        api_fan_mode = FAN_MODE_MAPPING_HA_TO_ACTRONAIR.get(fan_mode.lower())
        await self._status.user_aircon_settings.set_fan_mode(api_fan_mode)

    async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
        """Set the HVAC mode."""
        ac_mode = HVAC_MODE_MAPPING_HA_TO_ACTRONAIR.get(hvac_mode)
        await self._status.ac_system.set_system_mode(ac_mode)

    async def async_set_temperature(self, **kwargs: Any) -> None:
        """Set the temperature."""
        temp = kwargs.get(ATTR_TEMPERATURE)
        await self._status.user_aircon_settings.set_temperature(temperature=temp)


class ActronZoneClimate(BaseClimateEntity):
    """Representation of a zone within the Actron Air system."""

    _attr_supported_features = (
        ClimateEntityFeature.TARGET_TEMPERATURE
        | ClimateEntityFeature.TURN_ON
        | ClimateEntityFeature.TURN_OFF
    )

    def __init__(
        self,
        coordinator: ActronAirSystemCoordinator,
        zone: ActronAirNeoZone,
    ) -> None:
        """Initialize an Actron Air unit."""
        super().__init__(coordinator, zone.title)
        serial_number = coordinator.serial_number
        self._zone_id: int = zone.zone_id
        self._attr_unique_id: str = f"{serial_number}_zone_{zone.zone_id}"
        self._attr_device_info: DeviceInfo = DeviceInfo(
            identifiers={(DOMAIN, self._attr_unique_id)},
            name=zone.title,
            manufacturer="Actron Air",
            model="Zone",
            suggested_area=zone.title,
            via_device=(DOMAIN, serial_number),
        )

    @property
    def min_temp(self) -> float:
        """Return the minimum temperature that can be set."""
        return self._zone.min_temp

    @property
    def max_temp(self) -> float:
        """Return the maximum temperature that can be set."""
        return self._zone.max_temp

    @property
    def _zone(self) -> ActronAirNeoZone:
        """Get the current zone data from the coordinator."""
        status = self.coordinator.data
        return status.zones[self._zone_id]

    @property
    def hvac_mode(self) -> HVACMode | None:
        """Return the current HVAC mode."""
        if self._zone.is_active:
            mode = self._zone.hvac_mode
            return HVAC_MODE_MAPPING_ACTRONAIR_TO_HA.get(mode)
        return HVACMode.OFF

    @property
    def current_humidity(self) -> float | None:
        """Return the current humidity."""
        return self._zone.humidity

    @property
    def current_temperature(self) -> float | None:
        """Return the current temperature."""
        return self._zone.live_temp_c

    @property
    def target_temperature(self) -> float | None:
        """Return the target temperature."""
        return self._zone.temperature_setpoint_cool_c

    async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
        """Set the HVAC mode."""
        is_enabled = hvac_mode != HVACMode.OFF
        await self._zone.enable(is_enabled)

    async def async_set_temperature(self, **kwargs: Any) -> None:
        """Set the temperature."""
        await self._zone.set_temperature(temperature=kwargs["temperature"])
