# pylint: disable=protected-access, unused-argument, line-too-long
""" Test the Central Power management """
import asyncio
from unittest.mock import patch, AsyncMock, MagicMock, PropertyMock
from datetime import datetime, timedelta
import logging

from custom_components.versatile_thermostat.feature_power_manager import (
    FeaturePowerManager,
)
from custom_components.versatile_thermostat.central_feature_power_manager import (
    CentralFeaturePowerManager,
)

from custom_components.versatile_thermostat.thermostat_switch import (
    ThermostatOverSwitch,
)
from custom_components.versatile_thermostat.thermostat_climate import (
    ThermostatOverClimate,
)

from .commons import *  # pylint: disable=wildcard-import, unused-wildcard-import

logging.getLogger().setLevel(logging.DEBUG)


@pytest.mark.parametrize(
    "use_power_feature, power_entity_id, max_power_entity_id, power_temp, is_configured",
    [
        (True, "sensor.power_id", "sensor.max_power_id", 13, True),
        (True, None, "sensor.max_power_id", 13, False),
        (True, "sensor.power_id", None, 13, False),
        (True, "sensor.power_id", "sensor.max_power_id", None, False),
        (False, "sensor.power_id", "sensor.max_power_id", 13, False),
    ],
)
async def test_central_power_manager_init(
    hass: HomeAssistant,
    use_power_feature,
    power_entity_id,
    max_power_entity_id,
    power_temp,
    is_configured,
):
    """Test creation and post_init of the Central Power Manager"""
    vtherm_api: VersatileThermostatAPI = MagicMock(spec=VersatileThermostatAPI)
    central_power_manager = CentralFeaturePowerManager(hass, vtherm_api)

    assert central_power_manager.is_configured is False
    assert central_power_manager.current_max_power is None
    assert central_power_manager.current_power is None
    assert central_power_manager.power_temperature is None
    assert central_power_manager.name == "centralPowerManager"

    # 2. post_init
    central_power_manager.post_init(
        {
            CONF_POWER_SENSOR: power_entity_id,
            CONF_MAX_POWER_SENSOR: max_power_entity_id,
            CONF_USE_POWER_FEATURE: use_power_feature,
            CONF_PRESET_POWER: power_temp,
        }
    )

    assert central_power_manager.is_configured == is_configured
    assert central_power_manager.current_max_power is None
    assert central_power_manager.current_power is None
    assert central_power_manager.power_temperature == power_temp

    # 3. start listening
    await central_power_manager.start_listening()
    assert len(central_power_manager._active_listener) == (2 if is_configured else 0)

    # 4. stop listening
    central_power_manager.stop_listening()
    assert len(central_power_manager._active_listener) == 0


@pytest.mark.parametrize(
    "vtherm_configs, results",
    [
        # simple sort
        (
            [
                {
                    "name": "vtherm1",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 13,
                    "target_temperature": 12,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
                {
                    "name": "vtherm2",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 18,
                    "target_temperature": 12,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
                {
                    "name": "vtherm3",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 12,
                    "target_temperature": 18,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
            ],
            ["vtherm2", "vtherm1", "vtherm3"],
        ),
        # Ignore power not configured and not on
        (
            [
                {
                    "name": "vtherm1",
                    "is_configured": False,
                    "is_on": True,
                    "current_temperature": 13,
                    "target_temperature": 12,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
                {
                    "name": "vtherm2",
                    "is_configured": True,
                    "is_on": False,
                    "current_temperature": 18,
                    "target_temperature": 12,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
                {
                    "name": "vtherm3",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 12,
                    "target_temperature": 18,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
            ],
            ["vtherm3"],
        ),
        # None current_temperature are in last
        (
            [
                {
                    "name": "vtherm1",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 13,
                    "target_temperature": 12,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
                {
                    "name": "vtherm2",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": None,
                    "target_temperature": 12,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
                {
                    "name": "vtherm3",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 12,
                    "target_temperature": 18,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
            ],
            ["vtherm1", "vtherm3", "vtherm2"],
        ),
        # None target_temperature are in last
        (
            [
                {
                    "name": "vtherm1",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 13,
                    "target_temperature": 12,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
                {
                    "name": "vtherm2",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 18,
                    "target_temperature": None,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
                {
                    "name": "vtherm3",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 12,
                    "target_temperature": 18,
                    "saved_target_temp": 18,
                    "is_overpowering_detected": False,
                },
            ],
            ["vtherm1", "vtherm3", "vtherm2"],
        ),
        # simple sort with overpowering detected
        (
            [
                {
                    "name": "vtherm1",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 13,
                    # "target_temperature": 12,
                    "saved_target_temp": 21,
                    "is_overpowering_detected": True,
                },
                {
                    "name": "vtherm2",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 18,
                    # "target_temperature": 12,
                    "saved_target_temp": 17,
                    "is_overpowering_detected": True,
                },
                {
                    "name": "vtherm3",
                    "is_configured": True,
                    "is_on": True,
                    "current_temperature": 12,
                    # "target_temperature": 18,
                    "saved_target_temp": 16,
                    "is_overpowering_detected": True,
                },
            ],
            ["vtherm2", "vtherm3", "vtherm1"],
        ),
    ],
)
async def test_central_power_manageer_find_vtherms(
    hass: HomeAssistant, vtherm_configs, results
):
    """Test the find_all_vtherm_with_power_management_sorted_by_dtemp"""
    vtherm_api: VersatileThermostatAPI = MagicMock(spec=VersatileThermostatAPI)
    central_power_manager = CentralFeaturePowerManager(hass, vtherm_api)

    vtherms = []
    for vtherm_config in vtherm_configs:
        vtherm = MagicMock(spec=BaseThermostat)
        vtherm.name = vtherm_config.get("name")
        vtherm.is_on = vtherm_config.get("is_on")
        vtherm.current_temperature = vtherm_config.get("current_temperature")
        vtherm.target_temperature = vtherm_config.get("target_temperature")
        vtherm.saved_target_temp = vtherm_config.get("saved_target_temp")
        vtherm.power_manager.is_configured = vtherm_config.get("is_configured")
        vtherm.power_manager.is_overpowering_detected = vtherm_config.get("is_overpowering_detected")
        vtherms.append(vtherm)

    with patch(
        "custom_components.versatile_thermostat.central_feature_power_manager.CentralFeaturePowerManager.get_climate_components_entities",
        return_value=vtherms,
    ):
        vtherm_sorted = (
            central_power_manager.find_all_vtherm_with_power_management_sorted_by_dtemp()
        )

        # extract results
        vtherm_results = [vtherm.name for vtherm in vtherm_sorted]

        assert vtherm_results == results


@pytest.mark.parametrize(
    "current_power, current_max_power, vtherm_configs, expected_results",
    [
        # simple nominal test (initialize overpowering state in VTherm)
        (
            1000,
            5000,
            [
                {
                    "name": "vtherm1",
                    "device_power": 100,
                    "is_device_active": False,
                    "is_over_climate": False,
                    "nb_underlying_entities": 1,
                    "on_percent": 0,
                    "is_overpowering_detected": False,
                    "overpowering_state": STATE_UNKNOWN,
                },
                {
                    "name": "vtherm2",
                    "device_power": 10000,
                    "is_device_active": True,
                    "is_over_climate": False,
                    "nb_underlying_entities": 4,
                    "on_percent": 100,
                    "is_overpowering_detected": False,
                    "overpowering_state": STATE_UNKNOWN,
                },
                {
                    "name": "vtherm3",
                    "device_power": 5000,
                    "is_device_active": True,
                    "is_over_climate": True,
                    "is_overpowering_detected": False,
                    "overpowering_state": STATE_UNKNOWN,
                },
                {"name": "vtherm4", "device_power": 1000, "is_device_active": True, "is_over_climate": True, "is_overpowering_detected": False, "overpowering_state": STATE_OFF},
            ],
            # init vtherm1 to False
            {"vtherm3": False, "vtherm2": False, "vtherm1": False},
        ),
        # Un-shedding only (will be taken in reverse order)
        (
            1000,
            2000,
            [
                # should be not unshedded (too much power will be added)
                {
                    "name": "vtherm1",
                    "device_power": 800,
                    "is_device_active": False,
                    "is_over_climate": False,
                    "nb_underlying_entities": 1,
                    "on_percent": 1,
                    "is_overpowering_detected": True,
                    "overpowering_state": STATE_ON,
                },
                # already stay unshedded cause already unshedded
                {
                    "name": "vtherm2",
                    "device_power": 100,
                    "is_device_active": True,
                    "is_over_climate": True,
                    "is_overpowering_detected": False,
                    "overpowering_state": STATE_OFF,
                },
                # should be unshedded
                {
                    "name": "vtherm3",
                    "device_power": 200,
                    "is_device_active": False,
                    "is_over_climate": True,
                    "is_overpowering_detected": True,
                    "overpowering_state": STATE_ON,
                },
                # should be unshedded
                {
                    "name": "vtherm4",
                    "device_power": 300,
                    "is_device_active": False,
                    "is_over_climate": False,
                    "nb_underlying_entities": 1,
                    "on_percent": 1,
                    "is_overpowering_detected": True,
                    "overpowering_state": STATE_ON,
                },
            ],
            {"vtherm4": False, "vtherm3": False},
        ),
        # Shedding
        (
            2000,
            1000,
            [
                # should be overpowering
                {
                    "name": "vtherm1",
                    "device_power": 300,
                    "is_device_active": True,
                    "is_over_climate": False,
                    "nb_underlying_entities": 1,
                    "on_percent": 1,
                    "is_overpowering_detected": False,
                    "overpowering_state": STATE_OFF,
                },
                # should be overpowering with many underlmying entities
                {
                    "name": "vtherm2",
                    "device_power": 400,
                    "is_device_active": True,
                    "is_over_climate": False,
                    "nb_underlying_entities": 4,
                    "on_percent": 0.1,
                    "is_overpowering_detected": False,
                    "overpowering_state": STATE_UNKNOWN,
                },
                # over_climate should be overpowering
                {
                    "name": "vtherm3",
                    "device_power": 100,
                    "is_device_active": True,
                    "is_over_climate": True,
                    "is_overpowering_detected": False,
                    "overpowering_state": STATE_OFF,
                },
                # should pass cause not active
                {
                    "name": "vtherm4",
                    "device_power": 800,
                    "is_device_active": False,
                    "is_over_climate": False,
                    "nb_underlying_entities": 1,
                    "on_percent": 1,
                    "is_overpowering_detected": False,
                },
                # should be not overpowering (already overpowering)
                {
                    "name": "vtherm5",
                    "device_power": 400,
                    "is_device_active": True,
                    "is_over_climate": False,
                    "nb_underlying_entities": 4,
                    "on_percent": 0.1,
                    "is_overpowering_detected": True,
                    "overpowering_state": STATE_ON,
                },
                # should be overpowering with many underluying entities
                {
                    "name": "vtherm6",
                    "device_power": 400,
                    "is_device_active": True,
                    "is_over_climate": False,
                    "nb_underlying_entities": 4,
                    "on_percent": 0.1,
                    "is_overpowering_detected": False,
                    "overpowering_state": STATE_UNKNOWN,
                },
                # should not be overpowering (we have enough)
                {
                    "name": "vtherm7",
                    "device_power": 1000,
                    "is_device_active": True,
                    "is_over_climate": True,
                    "is_overpowering_detected": False,
                    "overpowering_state": STATE_UNKNOWN,
                },
            ],
            {"vtherm1": True, "vtherm2": True, "vtherm3": True, "vtherm6": True},
        ),
    ],
)
# @pytest.mark.skip
async def test_central_power_manageer_calculate_shedding(
    hass: HomeAssistant,
    current_power,
    current_max_power,
    vtherm_configs,
    expected_results,
):
    """Test the calculate_shedding of the CentralPowerManager"""
    vtherm_api: VersatileThermostatAPI = MagicMock(spec=VersatileThermostatAPI)
    central_power_manager = CentralFeaturePowerManager(hass, vtherm_api)

    registered_calls = {}

    def register_call(vtherm, overpowering):
        """Register a call to set_overpowering"""
        registered_calls.update({vtherm.name: overpowering})

    vtherms = []
    for vtherm_config in vtherm_configs:
        vtherm = MagicMock(spec=BaseThermostat)
        vtherm.name = vtherm_config.get("name")
        vtherm.is_device_active = vtherm_config.get("is_device_active")
        vtherm.is_over_climate = vtherm_config.get("is_over_climate")
        vtherm.nb_underlying_entities = vtherm_config.get("nb_underlying_entities")
        if not vtherm_config.get("is_over_climate"):
            vtherm.proportional_algorithm = MagicMock()
            vtherm.on_percent = vtherm.proportional_algorithm.on_percent = vtherm_config.get("on_percent")
        else:
            vtherm.on_percent = None
            vtherm.proportional_algorithm = None

        vtherm.power_manager = MagicMock(spec=FeaturePowerManager)
        vtherm.power_manager._vtherm = vtherm

        vtherm.power_manager.is_overpowering_detected = vtherm_config.get(
            "is_overpowering_detected"
        )
        vtherm.power_manager.device_power = vtherm_config.get("device_power")
        vtherm.power_manager.overpowering_state = vtherm_config.get("overpowering_state")

        async def mock_set_overpowering(
            overpowering, power_consumption_max=0, v=vtherm
        ):
            register_call(v, overpowering)

        vtherm.power_manager.set_overpowering = mock_set_overpowering

        vtherms.append(vtherm)

    # fmt:off
    with patch("custom_components.versatile_thermostat.central_feature_power_manager.CentralFeaturePowerManager.find_all_vtherm_with_power_management_sorted_by_dtemp", return_value=vtherms), \
        patch("custom_components.versatile_thermostat.central_feature_power_manager.CentralFeaturePowerManager.current_max_power", new_callable=PropertyMock, return_value=current_max_power), \
        patch("custom_components.versatile_thermostat.central_feature_power_manager.CentralFeaturePowerManager.current_power", new_callable=PropertyMock, return_value=current_power), \
        patch("custom_components.versatile_thermostat.central_feature_power_manager.CentralFeaturePowerManager.is_configured", new_callable=PropertyMock, return_value=True):
    # fmt:on

        await central_power_manager.calculate_shedding()

        # Check registered calls
        assert registered_calls == expected_results


@pytest.mark.parametrize(
    "dsecs, power, nb_call",
    [
        (0, 1000, 1),
        (0, None, 0),
        (0, STATE_UNAVAILABLE, 0),
        (0, STATE_UNKNOWN, 0),
        (21, 1000, 1),
        (19, 1000, 1),
    ],
)
async def test_central_power_manager_power_event(
    hass: HomeAssistant, dsecs, power, nb_call
):
    """Tests the Power sensor event"""
    vtherm_api: VersatileThermostatAPI = MagicMock(spec=VersatileThermostatAPI)
    central_power_manager = CentralFeaturePowerManager(hass, vtherm_api)

    assert central_power_manager.current_power is None
    assert central_power_manager.power_temperature is None
    assert central_power_manager.name == "centralPowerManager"

    # 2. post_init
    central_power_manager.post_init(
        {
            CONF_POWER_SENSOR: "sensor.power_entity_id",
            CONF_MAX_POWER_SENSOR: "sensor.max_power_entity_id",
            CONF_USE_POWER_FEATURE: True,
            CONF_PRESET_POWER: 13,
        }
    )

    assert central_power_manager.is_configured is True
    assert central_power_manager.current_max_power is None
    assert central_power_manager.current_power is None
    assert central_power_manager.power_temperature == 13

    # 3. start listening (not really useful but don't eat bread)
    await central_power_manager.start_listening()
    assert len(central_power_manager._active_listener) == 2

    now: datetime = NowClass.get_now(hass)
    # vtherm_api._set_now(now) vtherm_api is a MagicMock
    vtherm_api.now = now

    # 4. Call the _power_sensor_changed
    side_effects = SideEffects(
        {
            "sensor.power_entity_id": State("sensor.power_entity_id", power),
            "sensor.max_power_entity_id": State("sensor.max_power_entity_id", power),
        },
        State("unknown.entity_id", "unknown"),
    )
    # fmt:off
    with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()), \
         patch("custom_components.versatile_thermostat.central_feature_power_manager.CentralFeaturePowerManager.calculate_shedding", new_callable=AsyncMock) as mock_calculate_shedding:
    # fmt:on
        # set a default value to see if it has been replaced
        central_power_manager._current_power = -999
        await central_power_manager._power_sensor_changed(event=Event(
            event_type=EVENT_STATE_CHANGED,
            data={
                "entity_id": "sensor.power_entity_id",
                "new_state": State("sensor.power_entity_id", power),
                "old_state": State("sensor.power_entity_id", STATE_UNAVAILABLE),
            }))

        if nb_call > 0:
            await central_power_manager._do_immediate_shedding()

        expected_power = power if isinstance(power, (int, float)) else -999
        assert central_power_manager.current_power == expected_power
        assert mock_calculate_shedding.call_count == nb_call

    # Do another call x seconds later
    now = now + timedelta(seconds=dsecs)
    vtherm_api.now = now
    # fmt:off
    with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()), \
         patch("custom_components.versatile_thermostat.central_feature_power_manager.CentralFeaturePowerManager.calculate_shedding", new_callable=AsyncMock) as mock_calculate_shedding:
    # fmt:on
        central_power_manager._current_power = -999

        await central_power_manager._power_sensor_changed(event=Event(
            event_type=EVENT_STATE_CHANGED,
            data={
                "entity_id": "sensor.power_entity_id",
                "new_state": State("sensor.power_entity_id", power),
                "old_state": State("sensor.power_entity_id", STATE_UNAVAILABLE),
            }))

        if nb_call > 0:
            await central_power_manager._do_immediate_shedding()

        assert central_power_manager.current_power == expected_power
        assert mock_calculate_shedding.call_count == nb_call


@pytest.mark.parametrize(
    "dsecs, max_power, nb_call",
    [
        (0, 1000, 1),
        (0, None, 0),
        (0, STATE_UNAVAILABLE, 0),
        (0, STATE_UNKNOWN, 0),
        (21, 1000, 1),
        (19, 1000, 1),
    ],
)
async def test_central_power_manager_max_power_event(
    hass: HomeAssistant, dsecs, max_power, nb_call
):
    """Tests the Power sensor event"""
    vtherm_api: VersatileThermostatAPI = MagicMock(spec=VersatileThermostatAPI)
    central_power_manager = CentralFeaturePowerManager(hass, vtherm_api)

    assert central_power_manager.current_power is None
    assert central_power_manager.power_temperature is None
    assert central_power_manager.name == "centralPowerManager"

    # 2. post_init
    central_power_manager.post_init(
        {
            CONF_POWER_SENSOR: "sensor.power_entity_id",
            CONF_MAX_POWER_SENSOR: "sensor.max_power_entity_id",
            CONF_USE_POWER_FEATURE: True,
            CONF_PRESET_POWER: 13,
        }
    )

    assert central_power_manager.is_configured is True
    assert central_power_manager.current_max_power is None
    assert central_power_manager.current_power is None
    assert central_power_manager.power_temperature == 13

    # 3. start listening (not really useful but don't eat bread)
    await central_power_manager.start_listening()
    assert len(central_power_manager._active_listener) == 2

    now: datetime = NowClass.get_now(hass)
    # vtherm_api._set_now(now) vtherm_api is a MagicMock
    vtherm_api.now = now

    # 4. Call the _power_sensor_changed
    side_effects = SideEffects(
        {
            "sensor.power_entity_id": State("sensor.power_entity_id", max_power),
            "sensor.max_power_entity_id": State(
                "sensor.max_power_entity_id", max_power
            ),
        },
        State("unknown.entity_id", "unknown"),
    )
    # fmt:off
    with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()), \
         patch("custom_components.versatile_thermostat.central_feature_power_manager.CentralFeaturePowerManager.calculate_shedding", new_callable=AsyncMock) as mock_calculate_shedding:
    # fmt:on
        # set a default value to see if it has been replaced
        central_power_manager._current_max_power = -999
        await central_power_manager._power_sensor_changed(event=Event(
            event_type=EVENT_STATE_CHANGED,
            data={
                "entity_id": "sensor.max_power_entity_id",
                "new_state": State("sensor.max_power_entity_id", max_power),
                "old_state": State("sensor.max_power_entity_id", STATE_UNAVAILABLE),
            }))

        if nb_call > 0:
            await central_power_manager._do_immediate_shedding()

        expected_power = max_power if isinstance(max_power, (int, float)) else -999
        assert central_power_manager.current_max_power == expected_power
        assert mock_calculate_shedding.call_count == nb_call

    # Do another call x seconds later
    now = now + timedelta(seconds=dsecs)
    vtherm_api.now = now
    # fmt:off
    with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()), \
         patch("custom_components.versatile_thermostat.central_feature_power_manager.CentralFeaturePowerManager.calculate_shedding", new_callable=AsyncMock) as mock_calculate_shedding:
    # fmt:on
        central_power_manager._current_max_power = -999

        await central_power_manager._power_sensor_changed(event=Event(
            event_type=EVENT_STATE_CHANGED,
            data={
                "entity_id": "sensor.max_power_entity_id",
                "new_state": State("sensor.max_power_entity_id", max_power),
                "old_state": State("sensor.max_power_entity_id", STATE_UNAVAILABLE),
            }))

        if nb_call > 0:
            await central_power_manager._do_immediate_shedding()

        assert central_power_manager.current_max_power == expected_power
        assert mock_calculate_shedding.call_count == nb_call


async def test_central_power_manager_start_vtherm_power(hass: HomeAssistant, skip_hass_states_is_state, init_central_power_manager):
    """Tests the central power start VTherm power. The objective is to starts VTherm until the power max is exceeded"""

    temps = {
        "eco": 17,
        "comfort": 18,
        "boost": 19,
    }

    entry = MockConfigEntry(
        domain=DOMAIN,
        title="TheOverSwitchMockName",
        unique_id="uniqueId",
        data={
            CONF_NAME: "TheOverSwitchMockName",
            CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
            CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
            CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
            CONF_CYCLE_MIN: 5,
            CONF_TEMP_MIN: 15,
            CONF_TEMP_MAX: 30,
            CONF_USE_WINDOW_FEATURE: False,
            CONF_USE_MOTION_FEATURE: False,
            CONF_USE_POWER_FEATURE: True,
            CONF_USE_PRESENCE_FEATURE: False,
            CONF_UNDERLYING_LIST: ["switch.mock_switch"],
            CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
            CONF_TPI_COEF_INT: 0.3,
            CONF_TPI_COEF_EXT: 0.01,
            CONF_MINIMAL_ACTIVATION_DELAY: 30,
            CONF_SAFETY_DELAY_MIN: 5,
            CONF_SAFETY_MIN_ON_PERCENT: 0.3,
            CONF_DEVICE_POWER: 1000,
            CONF_PRESET_POWER: 12,
        },
    )

    entity: ThermostatOverSwitch = await create_thermostat(hass, entry, "climate.theoverswitchmockname", temps)
    assert entity

    now: datetime = NowClass.get_now(hass)
    VersatileThermostatAPI.get_vtherm_api()._set_now(now)

    central_power_manager = VersatileThermostatAPI.get_vtherm_api().central_power_manager
    assert central_power_manager

    side_effects = SideEffects(
        {
            "sensor.the_power_sensor": State("sensor.the_power_sensor", 1000),
            "sensor.the_max_power_sensor": State("sensor.the_max_power_sensor", 2100),
        },
        State("unknown.entity_id", "unknown"),
    )

    # 1. Make the heater heats
    # fmt: off
    with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()), \
         patch("custom_components.versatile_thermostat.thermostat_switch.ThermostatOverSwitch.is_device_active", new_callable=PropertyMock, return_value=False):
    # fmt: on
        # make the heater heats
        await send_power_change_event(entity, 1000, now)
        await send_max_power_change_event(entity, 2100, now)

        await send_temperature_change_event(entity, 15, now)
        await send_ext_temperature_change_event(entity, 1, now)

        await entity.async_set_preset_mode(PRESET_BOOST)
        assert entity.preset_mode is PRESET_BOOST
        assert entity.power_manager.overpowering_state is STATE_UNKNOWN
        assert entity.target_temperature == 19
        await hass.async_block_till_done()

        await entity.async_set_hvac_mode(HVACMode.HEAT)
        assert entity.hvac_mode is HVACMode.HEAT

        await hass.async_block_till_done()
        await asyncio.sleep(0.1)

        # the power of Vtherm should have been added
        assert central_power_manager.started_vtherm_total_power == 1000

    # 2. Check that another heater cannot heat
    entry2 = MockConfigEntry(
        domain=DOMAIN,
        title="TheOverClimateMockName2",
        unique_id="uniqueId2",
        data={
            CONF_NAME: "TheOverClimateMockName2",
            CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CLIMATE,
            CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
            CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
            CONF_CYCLE_MIN: 5,
            CONF_TEMP_MIN: 15,
            CONF_TEMP_MAX: 30,
            CONF_USE_WINDOW_FEATURE: False,
            CONF_USE_MOTION_FEATURE: False,
            CONF_USE_POWER_FEATURE: True,
            CONF_USE_PRESENCE_FEATURE: False,
            CONF_UNDERLYING_LIST: ["switch.mock_climate"],
            CONF_MINIMAL_ACTIVATION_DELAY: 30,
            CONF_SAFETY_DELAY_MIN: 5,
            CONF_SAFETY_MIN_ON_PERCENT: 0.3,
            CONF_DEVICE_POWER: 150,
            CONF_PRESET_POWER: 12,
        },
    )

    entity2: ThermostatOverClimate = await create_thermostat(hass, entry2, "climate.theoverclimatemockname2", temps)
    assert entity2

    fake_underlying_climate = MockClimate(
        hass=hass,
        unique_id="mockUniqueId",
        name="MockClimateName",
    )

    # fmt: off
    with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()), \
         patch("custom_components.versatile_thermostat.thermostat_switch.ThermostatOverSwitch.is_device_active", new_callable=PropertyMock, return_value=False), \
         patch("custom_components.versatile_thermostat.underlyings.UnderlyingClimate.find_underlying_climate",return_value=fake_underlying_climate):
    # fmt: on
        # make the heater heats
        await entity2.async_set_preset_mode(PRESET_COMFORT)
        assert entity2.preset_mode is PRESET_COMFORT
        assert entity2.power_manager.overpowering_state is STATE_UNKNOWN
        assert entity2.target_temperature == 18
        await entity2.async_set_hvac_mode(HVACMode.HEAT)
        assert entity2.hvac_mode is HVACMode.HEAT

        await hass.async_block_till_done()
        await asyncio.sleep(0.1)

        # the power of Vtherm should have not been added (cause it has not started) and the entity2 should be shedding
        assert central_power_manager.started_vtherm_total_power == 1000


        assert entity2.power_manager.overpowering_state is STATE_ON

    # 3. sends a new power sensor event
    await send_max_power_change_event(entity, 2150, now)
    # No change
    assert central_power_manager.started_vtherm_total_power == 1000

    await send_power_change_event(entity, 1010, now)
    assert central_power_manager.started_vtherm_total_power == 0
