"""Tests for miele vacuum module."""

from unittest.mock import MagicMock, Mock

from aiohttp import ClientResponseError
from pymiele import MieleDevices
import pytest
from syrupy.assertion import SnapshotAssertion

from homeassistant.components.miele.const import DOMAIN, PROCESS_ACTION, PROGRAM_ID
from homeassistant.components.vacuum import (
    ATTR_FAN_SPEED,
    DOMAIN as VACUUM_DOMAIN,
    SERVICE_CLEAN_SPOT,
    SERVICE_PAUSE,
    SERVICE_SET_FAN_SPEED,
    SERVICE_START,
    SERVICE_STOP,
)
from homeassistant.const import ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er

from . import get_actions_callback, get_data_callback

from tests.common import (
    MockConfigEntry,
    async_load_json_object_fixture,
    snapshot_platform,
)

ENTITY_ID = "vacuum.robot_vacuum_cleaner"

pytestmark = [
    pytest.mark.parametrize("platforms", [(Platform.VACUUM,)]),
    pytest.mark.parametrize("load_device_file", ["vacuum_device.json"]),
]


@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_sensor_states(
    hass: HomeAssistant,
    mock_miele_client: MagicMock,
    mock_config_entry: MockConfigEntry,
    snapshot: SnapshotAssertion,
    entity_registry: er.EntityRegistry,
    setup_platform: None,
) -> None:
    """Test vacuum entity setup."""

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


@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_vacuum_states_api_push(
    hass: HomeAssistant,
    mock_miele_client: MagicMock,
    snapshot: SnapshotAssertion,
    entity_registry: er.EntityRegistry,
    setup_platform: MockConfigEntry,
    device_fixture: MieleDevices,
) -> None:
    """Test vacuum state when the API pushes data via SSE."""

    data_callback = get_data_callback(mock_miele_client)
    await data_callback(device_fixture)
    await hass.async_block_till_done()

    act_file = await async_load_json_object_fixture(
        hass, "action_push_vacuum.json", DOMAIN
    )
    action_callback = get_actions_callback(mock_miele_client)
    await action_callback(act_file)
    await hass.async_block_till_done()

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


@pytest.mark.parametrize(
    ("service", "action_command", "vacuum_power"),
    [
        (SERVICE_START, PROCESS_ACTION, 1),
        (SERVICE_STOP, PROCESS_ACTION, 2),
        (SERVICE_PAUSE, PROCESS_ACTION, 3),
        (SERVICE_CLEAN_SPOT, PROGRAM_ID, 2),
    ],
)
async def test_vacuum_program(
    hass: HomeAssistant,
    mock_miele_client: MagicMock,
    setup_platform: None,
    service: str,
    vacuum_power: int | str,
    action_command: str,
) -> None:
    """Test the vacuum can be controlled."""

    await hass.services.async_call(
        VACUUM_DOMAIN, service, {ATTR_ENTITY_ID: ENTITY_ID}, blocking=True
    )
    mock_miele_client.send_action.assert_called_once_with(
        "Dummy_Vacuum_1", {action_command: vacuum_power}
    )


@pytest.mark.parametrize(
    ("fan_speed", "expected"), [("normal", 1), ("turbo", 3), ("silent", 4)]
)
async def test_vacuum_fan_speed(
    hass: HomeAssistant,
    mock_miele_client: MagicMock,
    setup_platform: None,
    fan_speed: str,
    expected: int,
) -> None:
    """Test the vacuum can be controlled."""

    await hass.services.async_call(
        VACUUM_DOMAIN,
        SERVICE_SET_FAN_SPEED,
        {ATTR_ENTITY_ID: ENTITY_ID, ATTR_FAN_SPEED: fan_speed},
        blocking=True,
    )
    mock_miele_client.send_action.assert_called_once_with(
        "Dummy_Vacuum_1", {"programId": expected}
    )


@pytest.mark.parametrize(
    ("service"),
    [
        (SERVICE_START),
        (SERVICE_STOP),
    ],
)
async def test_api_failure(
    hass: HomeAssistant,
    mock_miele_client: MagicMock,
    setup_platform: None,
    service: str,
) -> None:
    """Test handling of exception from API."""
    mock_miele_client.send_action.side_effect = ClientResponseError(Mock(), Mock())

    with pytest.raises(
        HomeAssistantError, match=f"Failed to set state for {ENTITY_ID}"
    ):
        await hass.services.async_call(
            VACUUM_DOMAIN, service, {ATTR_ENTITY_ID: ENTITY_ID}, blocking=True
        )
    mock_miele_client.send_action.assert_called_once()
