"""Provides triggers for air quality."""

from homeassistant.components.binary_sensor import (
    DOMAIN as BINARY_SENSOR_DOMAIN,
    BinarySensorDeviceClass,
)
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN, SensorDeviceClass
from homeassistant.const import STATE_OFF, STATE_ON, UnitOfDensity, UnitOfRatio
from homeassistant.core import HomeAssistant
from homeassistant.helpers.automation import DomainSpec
from homeassistant.helpers.trigger import (
    EntityTargetStateTriggerBase,
    Trigger,
    make_entity_numerical_state_changed_trigger,
    make_entity_numerical_state_changed_with_unit_trigger,
    make_entity_numerical_state_crossed_threshold_trigger,
    make_entity_numerical_state_crossed_threshold_with_unit_trigger,
    make_entity_target_state_trigger,
)
from homeassistant.util.unit_conversion import (
    CarbonMonoxideConcentrationConverter,
    MassVolumeConcentrationConverter,
    NitrogenDioxideConcentrationConverter,
    NitrogenMonoxideConcentrationConverter,
    OzoneConcentrationConverter,
    SulphurDioxideConcentrationConverter,
    UnitlessRatioConverter,
)


def _make_detected_trigger(
    device_class: BinarySensorDeviceClass,
) -> type[EntityTargetStateTriggerBase]:
    """Create a detected trigger for a binary sensor device class."""

    return make_entity_target_state_trigger(
        {BINARY_SENSOR_DOMAIN: DomainSpec(device_class=device_class)}, STATE_ON
    )


def _make_cleared_trigger(
    device_class: BinarySensorDeviceClass,
) -> type[EntityTargetStateTriggerBase]:
    """Create a cleared trigger for a binary sensor device class."""

    return make_entity_target_state_trigger(
        {BINARY_SENSOR_DOMAIN: DomainSpec(device_class=device_class)}, STATE_OFF
    )


TRIGGERS: dict[str, type[Trigger]] = {
    # Binary sensor triggers (detected/cleared)
    "gas_detected": _make_detected_trigger(BinarySensorDeviceClass.GAS),
    "gas_cleared": _make_cleared_trigger(BinarySensorDeviceClass.GAS),
    "co_detected": _make_detected_trigger(BinarySensorDeviceClass.CO),
    "co_cleared": _make_cleared_trigger(BinarySensorDeviceClass.CO),
    "smoke_detected": _make_detected_trigger(BinarySensorDeviceClass.SMOKE),
    "smoke_cleared": _make_cleared_trigger(BinarySensorDeviceClass.SMOKE),
    # Numerical sensor triggers with unit conversion
    "co_changed": make_entity_numerical_state_changed_with_unit_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.CO)},
        UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
        CarbonMonoxideConcentrationConverter,
    ),
    "co_crossed_threshold": (
        make_entity_numerical_state_crossed_threshold_with_unit_trigger(
            {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.CO)},
            UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
            CarbonMonoxideConcentrationConverter,
        )
    ),
    "ozone_changed": make_entity_numerical_state_changed_with_unit_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.OZONE)},
        UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
        OzoneConcentrationConverter,
    ),
    "ozone_crossed_threshold": (
        make_entity_numerical_state_crossed_threshold_with_unit_trigger(
            {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.OZONE)},
            UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
            OzoneConcentrationConverter,
        )
    ),
    "voc_changed": make_entity_numerical_state_changed_with_unit_trigger(
        {
            SENSOR_DOMAIN: DomainSpec(
                device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS
            )
        },
        UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
        MassVolumeConcentrationConverter,
    ),
    "voc_crossed_threshold": (
        make_entity_numerical_state_crossed_threshold_with_unit_trigger(
            {
                SENSOR_DOMAIN: DomainSpec(
                    device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS
                )
            },
            UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
            MassVolumeConcentrationConverter,
        )
    ),
    "voc_ratio_changed": make_entity_numerical_state_changed_with_unit_trigger(
        {
            SENSOR_DOMAIN: DomainSpec(
                device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS
            )
        },
        UnitOfRatio.PARTS_PER_BILLION,
        UnitlessRatioConverter,
    ),
    "voc_ratio_crossed_threshold": (
        make_entity_numerical_state_crossed_threshold_with_unit_trigger(
            {
                SENSOR_DOMAIN: DomainSpec(
                    device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS
                )
            },
            UnitOfRatio.PARTS_PER_BILLION,
            UnitlessRatioConverter,
        )
    ),
    "no_changed": make_entity_numerical_state_changed_with_unit_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.NITROGEN_MONOXIDE)},
        UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
        NitrogenMonoxideConcentrationConverter,
    ),
    "no_crossed_threshold": (
        make_entity_numerical_state_crossed_threshold_with_unit_trigger(
            {
                SENSOR_DOMAIN: DomainSpec(
                    device_class=SensorDeviceClass.NITROGEN_MONOXIDE
                )
            },
            UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
            NitrogenMonoxideConcentrationConverter,
        )
    ),
    "no2_changed": make_entity_numerical_state_changed_with_unit_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.NITROGEN_DIOXIDE)},
        UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
        NitrogenDioxideConcentrationConverter,
    ),
    "no2_crossed_threshold": (
        make_entity_numerical_state_crossed_threshold_with_unit_trigger(
            {
                SENSOR_DOMAIN: DomainSpec(
                    device_class=SensorDeviceClass.NITROGEN_DIOXIDE
                )
            },
            UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
            NitrogenDioxideConcentrationConverter,
        )
    ),
    "so2_changed": make_entity_numerical_state_changed_with_unit_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.SULPHUR_DIOXIDE)},
        UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
        SulphurDioxideConcentrationConverter,
    ),
    "so2_crossed_threshold": (
        make_entity_numerical_state_crossed_threshold_with_unit_trigger(
            {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.SULPHUR_DIOXIDE)},
            UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
            SulphurDioxideConcentrationConverter,
        )
    ),
    # Numerical sensor triggers without unit conversion (single-unit device classes)
    "co2_changed": make_entity_numerical_state_changed_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.CO2)},
        valid_unit=UnitOfRatio.PARTS_PER_MILLION,
    ),
    "co2_crossed_threshold": make_entity_numerical_state_crossed_threshold_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.CO2)},
        valid_unit=UnitOfRatio.PARTS_PER_MILLION,
    ),
    "pm1_changed": make_entity_numerical_state_changed_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.PM1)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
    "pm1_crossed_threshold": make_entity_numerical_state_crossed_threshold_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.PM1)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
    "pm25_changed": make_entity_numerical_state_changed_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.PM25)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
    "pm25_crossed_threshold": make_entity_numerical_state_crossed_threshold_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.PM25)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
    "pm4_changed": make_entity_numerical_state_changed_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.PM4)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
    "pm4_crossed_threshold": make_entity_numerical_state_crossed_threshold_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.PM4)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
    "pm10_changed": make_entity_numerical_state_changed_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.PM10)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
    "pm10_crossed_threshold": make_entity_numerical_state_crossed_threshold_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.PM10)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
    "n2o_changed": make_entity_numerical_state_changed_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.NITROUS_OXIDE)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
    "n2o_crossed_threshold": make_entity_numerical_state_crossed_threshold_trigger(
        {SENSOR_DOMAIN: DomainSpec(device_class=SensorDeviceClass.NITROUS_OXIDE)},
        valid_unit=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
    ),
}


async def async_get_triggers(hass: HomeAssistant) -> dict[str, type[Trigger]]:
    """Return the triggers for air quality."""
    return TRIGGERS
