"""Tests for the select module."""

from unittest.mock import AsyncMock, MagicMock, patch

from eheimdigital.types import FilterMode, FilterModeProf, ReeflexMode
import pytest
from syrupy.assertion import SnapshotAssertion

from homeassistant.components.select import (
    ATTR_OPTION,
    DOMAIN as SELECT_DOMAIN,
    SERVICE_SELECT_OPTION,
)
from homeassistant.const import ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er

from .conftest import init_integration

from tests.common import MockConfigEntry, snapshot_platform


async def test_setup(
    hass: HomeAssistant,
    eheimdigital_hub_mock: MagicMock,
    mock_config_entry: MockConfigEntry,
    entity_registry: er.EntityRegistry,
    snapshot: SnapshotAssertion,
) -> None:
    """Test select platform setup."""
    mock_config_entry.add_to_hass(hass)

    with (
        patch("homeassistant.components.eheimdigital.PLATFORMS", [Platform.SELECT]),
        patch(
            "homeassistant.components.eheimdigital.coordinator.asyncio.Event",
            new=AsyncMock,
        ),
    ):
        await hass.config_entries.async_setup(mock_config_entry.entry_id)

    for device in eheimdigital_hub_mock.return_value.devices:
        await eheimdigital_hub_mock.call_args.kwargs["device_found_callback"](
            device, eheimdigital_hub_mock.return_value.devices[device].device_type
        )
        await hass.async_block_till_done()

    await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)


@pytest.mark.parametrize(
    ("device_name", "entity_list"),
    [
        (
            "classic_vario_mock",
            [
                (
                    "select.mock_aquarium_mock_classicvario_filter_mode",
                    "manual",
                    "pumpMode",
                    int(FilterMode.MANUAL),
                ),
            ],
        ),
        (
            "filter_mock",
            [
                (
                    "select.mock_aquarium_mock_filter_filter_mode",
                    "constant_flow",
                    "title",
                    "START_FILTER_NORMAL_MODE_WITH_COMP",
                ),
                (
                    "select.mock_aquarium_mock_filter_manual_speed",
                    "61.5",
                    "frequency",
                    int(61.5 * 100),
                ),
                (
                    "select.mock_aquarium_mock_filter_constant_flow_speed",
                    "440",
                    "flow_rate",
                    1,
                ),
                (
                    "select.mock_aquarium_mock_filter_day_speed",
                    "480",
                    "dfs_soll_day",
                    2,
                ),
                (
                    "select.mock_aquarium_mock_filter_night_speed",
                    "860",
                    "dfs_soll_night",
                    14,
                ),
                (
                    "select.mock_aquarium_mock_filter_high_pulse_speed",
                    "620",
                    "dfs_soll_high",
                    6,
                ),
                (
                    "select.mock_aquarium_mock_filter_low_pulse_speed",
                    "770",
                    "dfs_soll_low",
                    11,
                ),
            ],
        ),
        (
            "reeflex_mock",
            [
                (
                    "select.mock_aquarium_mock_reeflex_operation_mode",
                    "constant",
                    "mode",
                    int(ReeflexMode.CONSTANT),
                ),
            ],
        ),
    ],
)
async def test_set_value(
    hass: HomeAssistant,
    eheimdigital_hub_mock: MagicMock,
    mock_config_entry: MockConfigEntry,
    device_name: str,
    entity_list: list[tuple[str, str, str, int]],
    request: pytest.FixtureRequest,
) -> None:
    """Test setting a value."""
    device: MagicMock = request.getfixturevalue(device_name)
    await init_integration(hass, mock_config_entry)

    await eheimdigital_hub_mock.call_args.kwargs["device_found_callback"](
        device.mac_address, device.device_type
    )

    await hass.async_block_till_done()

    for item in entity_list:
        await hass.services.async_call(
            SELECT_DOMAIN,
            SERVICE_SELECT_OPTION,
            {ATTR_ENTITY_ID: item[0], ATTR_OPTION: item[1]},
            blocking=True,
        )
        calls = [call for call in device.hub.mock_calls if call[0] == "send_packet"]
        assert calls[-1][1][0][item[2]] == item[3]


@pytest.mark.usefixtures("classic_vario_mock", "heater_mock")
@pytest.mark.parametrize(
    ("device_name", "entity_list"),
    [
        (
            "classic_vario_mock",
            [
                (
                    "select.mock_aquarium_mock_classicvario_filter_mode",
                    "classic_vario_data",
                    "pumpMode",
                    int(FilterMode.BIO),
                    "bio",
                ),
            ],
        ),
        (
            "filter_mock",
            [
                (
                    "select.mock_aquarium_mock_filter_filter_mode",
                    "filter_data",
                    "pumpMode",
                    int(FilterModeProf.CONSTANT_FLOW),
                    "constant_flow",
                ),
                (
                    "select.mock_aquarium_mock_filter_manual_speed",
                    "filter_data",
                    "freqSoll",
                    int(61.5 * 100),
                    "61.5",
                ),
                (
                    "select.mock_aquarium_mock_filter_constant_flow_speed",
                    "filter_data",
                    "sollStep",
                    1,
                    "440",
                ),
                (
                    "select.mock_aquarium_mock_filter_day_speed",
                    "filter_data",
                    "nm_dfs_soll_day",
                    2,
                    "480",
                ),
                (
                    "select.mock_aquarium_mock_filter_night_speed",
                    "filter_data",
                    "nm_dfs_soll_night",
                    14,
                    "860",
                ),
                (
                    "select.mock_aquarium_mock_filter_high_pulse_speed",
                    "filter_data",
                    "pm_dfs_soll_high",
                    6,
                    "620",
                ),
                (
                    "select.mock_aquarium_mock_filter_low_pulse_speed",
                    "filter_data",
                    "pm_dfs_soll_low",
                    11,
                    "770",
                ),
            ],
        ),
        (
            "reeflex_mock",
            [
                (
                    "select.mock_aquarium_mock_reeflex_operation_mode",
                    "reeflex_data",
                    "mode",
                    int(ReeflexMode.CONSTANT),
                    "constant",
                ),
            ],
        ),
    ],
)
async def test_state_update(
    hass: HomeAssistant,
    eheimdigital_hub_mock: MagicMock,
    mock_config_entry: MockConfigEntry,
    device_name: str,
    entity_list: list[tuple[str, str, str, int, str]],
    request: pytest.FixtureRequest,
) -> None:
    """Test state updates."""
    device: MagicMock = request.getfixturevalue(device_name)
    await init_integration(hass, mock_config_entry)

    await eheimdigital_hub_mock.call_args.kwargs["device_found_callback"](
        device.mac_address, device.device_type
    )

    await hass.async_block_till_done()

    for item in entity_list:
        getattr(device, item[1])[item[2]] = item[3]
        await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
        assert (state := hass.states.get(item[0]))
        assert state.state == item[4]
