"""The test for the sensibo binary sensor platform."""
from __future__ import annotations

from datetime import datetime, timedelta
from unittest.mock import patch

from pysensibo.model import SensiboData
import pytest
from syrupy.assertion import SnapshotAssertion
from voluptuous import MultipleInvalid

from homeassistant.components.climate import (
    ATTR_FAN_MODE,
    ATTR_HVAC_MODE,
    ATTR_SWING_MODE,
    ATTR_TARGET_TEMP_HIGH,
    ATTR_TARGET_TEMP_LOW,
    DOMAIN as CLIMATE_DOMAIN,
    SERVICE_SET_FAN_MODE,
    SERVICE_SET_HVAC_MODE,
    SERVICE_SET_SWING_MODE,
    SERVICE_SET_TEMPERATURE,
)
from homeassistant.components.sensibo.climate import (
    ATTR_AC_INTEGRATION,
    ATTR_GEO_INTEGRATION,
    ATTR_HIGH_TEMPERATURE_STATE,
    ATTR_HIGH_TEMPERATURE_THRESHOLD,
    ATTR_HORIZONTAL_SWING_MODE,
    ATTR_INDOOR_INTEGRATION,
    ATTR_LIGHT,
    ATTR_LOW_TEMPERATURE_STATE,
    ATTR_LOW_TEMPERATURE_THRESHOLD,
    ATTR_MINUTES,
    ATTR_OUTDOOR_INTEGRATION,
    ATTR_SENSITIVITY,
    ATTR_SMART_TYPE,
    ATTR_TARGET_TEMPERATURE,
    SERVICE_ASSUME_STATE,
    SERVICE_ENABLE_CLIMATE_REACT,
    SERVICE_ENABLE_PURE_BOOST,
    SERVICE_ENABLE_TIMER,
    SERVICE_FULL_STATE,
    _find_valid_target_temp,
)
from homeassistant.components.sensibo.const import DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
    ATTR_ENTITY_ID,
    ATTR_MODE,
    ATTR_STATE,
    ATTR_TEMPERATURE,
    SERVICE_TURN_OFF,
    SERVICE_TURN_ON,
    STATE_UNKNOWN,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.util import dt as dt_util

from tests.common import async_fire_time_changed


async def test_climate_find_valid_targets() -> None:
    """Test function to return temperature from valid targets."""

    valid_targets = [10, 16, 17, 18, 19, 20]

    assert _find_valid_target_temp(7, valid_targets) == 10
    assert _find_valid_target_temp(10, valid_targets) == 10
    assert _find_valid_target_temp(11, valid_targets) == 16
    assert _find_valid_target_temp(15, valid_targets) == 16
    assert _find_valid_target_temp(16, valid_targets) == 16
    assert _find_valid_target_temp(18.5, valid_targets) == 19
    assert _find_valid_target_temp(20, valid_targets) == 20
    assert _find_valid_target_temp(25, valid_targets) == 20


async def test_climate(
    hass: HomeAssistant,
    caplog: pytest.LogCaptureFixture,
    get_data: SensiboData,
    load_int: ConfigEntry,
    snapshot: SnapshotAssertion,
) -> None:
    """Test the Sensibo climate."""

    state1 = hass.states.get("climate.hallway")
    state2 = hass.states.get("climate.kitchen")
    state3 = hass.states.get("climate.bedroom")

    assert state1.state == "heat"
    assert state1.attributes == snapshot

    assert state2.state == "off"

    assert state3
    assert state3.state == "off"
    found_log = False
    logs = caplog.get_records("setup")
    for log in logs:
        if (
            log.message
            == "Device Bedroom not correctly registered with remote on Sensibo cloud."
        ):
            found_log = True
            break

    assert found_log


async def test_climate_fan(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate fan service."""

    state1 = hass.states.get("climate.hallway")
    assert state1.attributes["fan_mode"] == "high"

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_FAN_MODE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_FAN_MODE: "low"},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["fan_mode"] == "low"

    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "active_features",
        [
            "timestamp",
            "on",
            "mode",
            "swing",
            "targetTemperature",
            "horizontalSwing",
            "light",
        ],
    )
    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
    ), pytest.raises(HomeAssistantError):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_FAN_MODE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_FAN_MODE: "low"},
            blocking=True,
        )
    await hass.async_block_till_done()

    state3 = hass.states.get("climate.hallway")
    assert state3.attributes["fan_mode"] == "low"


async def test_climate_swing(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate swing service."""

    state1 = hass.states.get("climate.hallway")
    assert state1.attributes["swing_mode"] == "stopped"

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_SWING_MODE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_SWING_MODE: "fixedtop"},
            blocking=True,
        )
        await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["swing_mode"] == "fixedtop"

    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "active_features",
        [
            "timestamp",
            "on",
            "mode",
            "targetTemperature",
            "horizontalSwing",
            "light",
        ],
    )
    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
    ), pytest.raises(HomeAssistantError):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_SWING_MODE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_SWING_MODE: "fixedtop"},
            blocking=True,
        )
    await hass.async_block_till_done()

    state3 = hass.states.get("climate.hallway")
    assert state3.attributes["swing_mode"] == "fixedtop"


async def test_climate_temperatures(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate temperature service."""

    state1 = hass.states.get("climate.hallway")
    assert state1.attributes["temperature"] == 25

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_TEMPERATURE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_TEMPERATURE: 20},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["temperature"] == 20

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_TEMPERATURE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_TEMPERATURE: 15},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["temperature"] == 16

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_TEMPERATURE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_TEMPERATURE: 18.5},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["temperature"] == 19

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_TEMPERATURE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_TEMPERATURE: 24},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["temperature"] == 20

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_TEMPERATURE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_TEMPERATURE: 20},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["temperature"] == 20

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ), pytest.raises(MultipleInvalid):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_TEMPERATURE,
            {ATTR_ENTITY_ID: state1.entity_id},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["temperature"] == 20

    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "active_features",
        [
            "timestamp",
            "on",
            "mode",
            "swing",
            "horizontalSwing",
            "light",
        ],
    )
    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ), pytest.raises(HomeAssistantError):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_TEMPERATURE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_TEMPERATURE: 20},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["temperature"] == 20


async def test_climate_temperature_is_none(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate temperature service no temperature provided."""

    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "active_features",
        [
            "timestamp",
            "on",
            "mode",
            "fanLevel",
            "targetTemperature",
            "swing",
            "horizontalSwing",
            "light",
        ],
    )
    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "target_temp",
        25,
    )
    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state1 = hass.states.get("climate.hallway")
    assert state1.attributes["temperature"] == 25

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
    ), pytest.raises(ValueError):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_TEMPERATURE,
            {
                ATTR_ENTITY_ID: state1.entity_id,
                ATTR_TARGET_TEMP_HIGH: 30,
                ATTR_TARGET_TEMP_LOW: 20,
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["temperature"] == 25


async def test_climate_hvac_mode(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate hvac mode service."""

    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "active_features",
        [
            "timestamp",
            "on",
            "mode",
            "fanLevel",
            "targetTemperature",
            "swing",
            "horizontalSwing",
            "light",
        ],
    )
    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state1 = hass.states.get("climate.hallway")
    assert state1.state == "heat"

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_HVAC_MODE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_HVAC_MODE: "off"},
            blocking=True,
        )
        await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.state == "off"

    monkeypatch.setattr(get_data.parsed["ABC999111"], "device_on", False)
    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_HVAC_MODE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_HVAC_MODE: "heat"},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.state == "heat"


async def test_climate_on_off(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate on/off service."""

    monkeypatch.setattr(get_data.parsed["ABC999111"], "hvac_mode", "heat")
    monkeypatch.setattr(get_data.parsed["ABC999111"], "device_on", True)
    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state1 = hass.states.get("climate.hallway")
    assert state1.state == "heat"

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_TURN_OFF,
            {ATTR_ENTITY_ID: state1.entity_id},
            blocking=True,
        )
        await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.state == "off"

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_TURN_ON,
            {ATTR_ENTITY_ID: state1.entity_id},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.state == "heat"


async def test_climate_service_failed(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate service failed."""

    monkeypatch.setattr(get_data.parsed["ABC999111"], "hvac_mode", "heat")
    monkeypatch.setattr(get_data.parsed["ABC999111"], "device_on", True)
    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state1 = hass.states.get("climate.hallway")
    assert state1.state == "heat"

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Error", "failureReason": "Did not work"}},
    ), pytest.raises(HomeAssistantError):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_TURN_OFF,
            {ATTR_ENTITY_ID: state1.entity_id},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.state == "heat"


async def test_climate_assumed_state(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate assumed state service."""

    monkeypatch.setattr(get_data.parsed["ABC999111"], "hvac_mode", "heat")
    monkeypatch.setattr(get_data.parsed["ABC999111"], "device_on", True)
    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state1 = hass.states.get("climate.hallway")
    assert state1.state == "heat"

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_ASSUME_STATE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_STATE: "off"},
            blocking=True,
        )
    await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.state == "off"


async def test_climate_no_fan_no_swing(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate fan service."""

    state = hass.states.get("climate.hallway")
    assert state.attributes["fan_mode"] == "high"
    assert state.attributes["swing_mode"] == "stopped"

    monkeypatch.setattr(get_data.parsed["ABC999111"], "fan_mode", None)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "swing_mode", None)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "fan_modes", None)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "swing_modes", None)

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state = hass.states.get("climate.hallway")
    assert state.attributes["fan_mode"] is None
    assert state.attributes["swing_mode"] is None
    assert state.attributes["fan_modes"] is None
    assert state.attributes["swing_modes"] is None


async def test_climate_set_timer(
    hass: HomeAssistant,
    entity_registry_enabled_by_default: None,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate Set Timer service."""

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state_climate = hass.states.get("climate.hallway")
    assert hass.states.get("sensor.hallway_timer_end_time").state == STATE_UNKNOWN

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_timer",
        return_value={"status": "failure"},
    ), pytest.raises(
        MultipleInvalid
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_ENABLE_TIMER,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_timer",
        return_value={"status": "failure"},
    ), pytest.raises(
        HomeAssistantError
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_ENABLE_TIMER,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
                ATTR_MINUTES: 30,
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_timer",
        return_value={"status": "success", "result": {"id": "SzTGE4oZ4D"}},
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_ENABLE_TIMER,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
                ATTR_MINUTES: 30,
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    monkeypatch.setattr(get_data.parsed["ABC999111"], "timer_on", True)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "timer_id", "SzTGE4oZ4D")
    monkeypatch.setattr(get_data.parsed["ABC999111"], "timer_state_on", False)
    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "timer_time",
        datetime(2022, 6, 6, 12, 00, 00, tzinfo=dt_util.UTC),
    )

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    assert (
        hass.states.get("sensor.hallway_timer_end_time").state
        == "2022-06-06T12:00:00+00:00"
    )


async def test_climate_pure_boost(
    hass: HomeAssistant,
    entity_registry_enabled_by_default: None,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate assumed state service."""

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state_climate = hass.states.get("climate.kitchen")
    state2 = hass.states.get("switch.kitchen_pure_boost")
    assert state2.state == "off"

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_pureboost",
    ), pytest.raises(
        MultipleInvalid
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_ENABLE_PURE_BOOST,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
                ATTR_INDOOR_INTEGRATION: True,
                ATTR_OUTDOOR_INTEGRATION: True,
                ATTR_SENSITIVITY: "Sensitive",
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_pureboost",
        return_value={
            "status": "success",
            "result": {
                "enabled": True,
                "sensitivity": "S",
                "measurements_integration": True,
                "ac_integration": False,
                "geo_integration": False,
                "prime_integration": True,
            },
        },
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_ENABLE_PURE_BOOST,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
                ATTR_AC_INTEGRATION: False,
                ATTR_GEO_INTEGRATION: False,
                ATTR_INDOOR_INTEGRATION: True,
                ATTR_OUTDOOR_INTEGRATION: True,
                ATTR_SENSITIVITY: "Sensitive",
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pure_boost_enabled", True)
    monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pure_sensitivity", "s")
    monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pure_measure_integration", True)
    monkeypatch.setattr(get_data.parsed["AAZZAAZZ"], "pure_prime_integration", True)

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state1 = hass.states.get("switch.kitchen_pure_boost")
    state2 = hass.states.get(
        "binary_sensor.kitchen_pure_boost_linked_with_indoor_air_quality"
    )
    state3 = hass.states.get(
        "binary_sensor.kitchen_pure_boost_linked_with_outdoor_air_quality"
    )
    state4 = hass.states.get("sensor.kitchen_pure_sensitivity")
    assert state1.state == "on"
    assert state2.state == "on"
    assert state3.state == "on"
    assert state4.state == "s"


async def test_climate_climate_react(
    hass: HomeAssistant,
    entity_registry_enabled_by_default: None,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate react custom service."""

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state_climate = hass.states.get("climate.hallway")

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_climate_react",
    ), pytest.raises(
        MultipleInvalid
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_ENABLE_PURE_BOOST,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
                ATTR_LOW_TEMPERATURE_THRESHOLD: 0.2,
                ATTR_HIGH_TEMPERATURE_THRESHOLD: 30.3,
                ATTR_SMART_TYPE: "temperature",
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_climate_react",
        return_value={
            "status": "success",
            "result": {
                "enabled": True,
                "deviceUid": "ABC999111",
                "highTemperatureState": {
                    "on": True,
                    "targetTemperature": 15,
                    "temperatureUnit": "C",
                    "mode": "cool",
                    "fanLevel": "high",
                    "swing": "stopped",
                    "horizontalSwing": "stopped",
                    "light": "on",
                },
                "highTemperatureThreshold": 30.5,
                "lowTemperatureState": {
                    "on": True,
                    "targetTemperature": 25,
                    "temperatureUnit": "C",
                    "mode": "heat",
                    "fanLevel": "low",
                    "swing": "stopped",
                    "horizontalSwing": "stopped",
                    "light": "on",
                },
                "lowTemperatureThreshold": 5.5,
                "type": "temperature",
            },
        },
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_ENABLE_CLIMATE_REACT,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
                ATTR_LOW_TEMPERATURE_THRESHOLD: 5.5,
                ATTR_HIGH_TEMPERATURE_THRESHOLD: 30.5,
                ATTR_LOW_TEMPERATURE_STATE: {
                    "on": True,
                    "targetTemperature": 25,
                    "temperatureUnit": "C",
                    "mode": "heat",
                    "fanLevel": "low",
                    "swing": "stopped",
                    "horizontalSwing": "stopped",
                    "light": "on",
                },
                ATTR_HIGH_TEMPERATURE_STATE: {
                    "on": True,
                    "targetTemperature": 15,
                    "temperatureUnit": "C",
                    "mode": "cool",
                    "fanLevel": "high",
                    "swing": "stopped",
                    "horizontalSwing": "stopped",
                    "light": "on",
                },
                ATTR_SMART_TYPE: "temperature",
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_on", True)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_type", "temperature")
    monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_low_temp_threshold", 5.5)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_high_temp_threshold", 30.5)
    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "smart_low_state",
        {
            "on": True,
            "targetTemperature": 25,
            "temperatureUnit": "C",
            "mode": "heat",
            "fanLevel": "low",
            "swing": "stopped",
            "horizontalSwing": "stopped",
            "light": "on",
        },
    )
    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "smart_high_state",
        {
            "on": True,
            "targetTemperature": 15,
            "temperatureUnit": "C",
            "mode": "cool",
            "fanLevel": "high",
            "swing": "stopped",
            "horizontalSwing": "stopped",
            "light": "on",
        },
    )

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state1 = hass.states.get("switch.hallway_climate_react")
    state2 = hass.states.get("sensor.hallway_climate_react_low_temperature_threshold")
    state3 = hass.states.get("sensor.hallway_climate_react_high_temperature_threshold")
    state4 = hass.states.get("sensor.hallway_climate_react_type")
    assert state1.state == "on"
    assert state2.state == "5.5"
    assert state3.state == "30.5"
    assert state4.state == "temperature"


async def test_climate_climate_react_fahrenheit(
    hass: HomeAssistant,
    entity_registry_enabled_by_default: None,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate react custom service with fahrenheit."""

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state_climate = hass.states.get("climate.hallway")

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_climate_react",
        return_value={
            "status": "success",
            "result": {
                "enabled": True,
                "deviceUid": "ABC999111",
                "highTemperatureState": {
                    "on": True,
                    "targetTemperature": 65,
                    "temperatureUnit": "F",
                    "mode": "cool",
                    "fanLevel": "high",
                    "swing": "stopped",
                    "horizontalSwing": "stopped",
                    "light": "on",
                },
                "highTemperatureThreshold": 77,
                "lowTemperatureState": {
                    "on": True,
                    "targetTemperature": 85,
                    "temperatureUnit": "F",
                    "mode": "heat",
                    "fanLevel": "low",
                    "swing": "stopped",
                    "horizontalSwing": "stopped",
                    "light": "on",
                },
                "lowTemperatureThreshold": 32,
                "type": "temperature",
            },
        },
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_ENABLE_CLIMATE_REACT,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
                ATTR_LOW_TEMPERATURE_THRESHOLD: 32.0,
                ATTR_HIGH_TEMPERATURE_THRESHOLD: 77.0,
                ATTR_LOW_TEMPERATURE_STATE: {
                    "on": True,
                    "targetTemperature": 85,
                    "temperatureUnit": "F",
                    "mode": "heat",
                    "fanLevel": "low",
                    "swing": "stopped",
                    "horizontalSwing": "stopped",
                    "light": "on",
                },
                ATTR_HIGH_TEMPERATURE_STATE: {
                    "on": True,
                    "targetTemperature": 65,
                    "temperatureUnit": "F",
                    "mode": "cool",
                    "fanLevel": "high",
                    "swing": "stopped",
                    "horizontalSwing": "stopped",
                    "light": "on",
                },
                ATTR_SMART_TYPE: "temperature",
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_on", True)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_type", "temperature")
    monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_low_temp_threshold", 0)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "smart_high_temp_threshold", 25)
    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "smart_low_state",
        {
            "on": True,
            "targetTemperature": 85,
            "temperatureUnit": "F",
            "mode": "heat",
            "fanLevel": "low",
            "swing": "stopped",
            "horizontalSwing": "stopped",
            "light": "on",
        },
    )
    monkeypatch.setattr(
        get_data.parsed["ABC999111"],
        "smart_high_state",
        {
            "on": True,
            "targetTemperature": 65,
            "temperatureUnit": "F",
            "mode": "cool",
            "fanLevel": "high",
            "swing": "stopped",
            "horizontalSwing": "stopped",
            "light": "on",
        },
    )

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state1 = hass.states.get("switch.hallway_climate_react")
    state2 = hass.states.get("sensor.hallway_climate_react_low_temperature_threshold")
    state3 = hass.states.get("sensor.hallway_climate_react_high_temperature_threshold")
    state4 = hass.states.get("sensor.hallway_climate_react_type")
    assert state1.state == "on"
    assert state2.state == "0"
    assert state3.state == "25"
    assert state4.state == "temperature"


async def test_climate_full_ac_state(
    hass: HomeAssistant,
    entity_registry_enabled_by_default: None,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate Full AC state service."""

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state_climate = hass.states.get("climate.hallway")
    assert state_climate.state == "heat"

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_states",
    ), pytest.raises(
        MultipleInvalid
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_FULL_STATE,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
                ATTR_TARGET_TEMPERATURE: 22,
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ), patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_states",
        return_value={"result": {"status": "Success"}},
    ):
        await hass.services.async_call(
            DOMAIN,
            SERVICE_FULL_STATE,
            {
                ATTR_ENTITY_ID: state_climate.entity_id,
                ATTR_MODE: "cool",
                ATTR_TARGET_TEMPERATURE: 22,
                ATTR_FAN_MODE: "high",
                ATTR_SWING_MODE: "stopped",
                ATTR_HORIZONTAL_SWING_MODE: "stopped",
                ATTR_LIGHT: "on",
            },
            blocking=True,
        )
    await hass.async_block_till_done()

    monkeypatch.setattr(get_data.parsed["ABC999111"], "hvac_mode", "cool")
    monkeypatch.setattr(get_data.parsed["ABC999111"], "device_on", True)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "target_temp", 22)
    monkeypatch.setattr(get_data.parsed["ABC999111"], "fan_mode", "high")
    monkeypatch.setattr(get_data.parsed["ABC999111"], "swing_mode", "stopped")
    monkeypatch.setattr(
        get_data.parsed["ABC999111"], "horizontal_swing_mode", "stopped"
    )
    monkeypatch.setattr(get_data.parsed["ABC999111"], "light_mode", "on")

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state = hass.states.get("climate.hallway")

    assert state.state == "cool"
    assert state.attributes["temperature"] == 22


async def test_climate_fan_mode_and_swing_mode_not_supported(
    hass: HomeAssistant,
    load_int: ConfigEntry,
    monkeypatch: pytest.MonkeyPatch,
    get_data: SensiboData,
) -> None:
    """Test the Sensibo climate fan_mode and swing_mode not supported is raising error."""

    state1 = hass.states.get("climate.hallway")
    assert state1.attributes["fan_mode"] == "high"
    assert state1.attributes["swing_mode"] == "stopped"

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
    ), pytest.raises(
        HomeAssistantError,
        match="Climate swing mode faulty_swing_mode is not supported by the integration, please open an issue",
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_SWING_MODE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_SWING_MODE: "faulty_swing_mode"},
            blocking=True,
        )

    with patch(
        "homeassistant.components.sensibo.util.SensiboClient.async_set_ac_state_property",
    ), pytest.raises(
        HomeAssistantError,
        match="Climate fan mode faulty_fan_mode is not supported by the integration, please open an issue",
    ):
        await hass.services.async_call(
            CLIMATE_DOMAIN,
            SERVICE_SET_FAN_MODE,
            {ATTR_ENTITY_ID: state1.entity_id, ATTR_FAN_MODE: "faulty_fan_mode"},
            blocking=True,
        )

    with patch(
        "homeassistant.components.sensibo.coordinator.SensiboClient.async_get_devices_data",
        return_value=get_data,
    ):
        async_fire_time_changed(
            hass,
            dt_util.utcnow() + timedelta(minutes=5),
        )
        await hass.async_block_till_done()

    state2 = hass.states.get("climate.hallway")
    assert state2.attributes["fan_mode"] == "high"
    assert state2.attributes["swing_mode"] == "stopped"