"""Test the Litter-Robot vacuum entity."""

from __future__ import annotations

from typing import Any
from unittest.mock import MagicMock

from pylitterbot import Robot
import pytest

from homeassistant.components.litterrobot.services import SERVICE_SET_SLEEP_MODE
from homeassistant.components.vacuum import (
    DOMAIN as VACUUM_DOMAIN,
    SERVICE_START,
    SERVICE_STOP,
    VacuumActivity,
)
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er, issue_registry as ir

from .common import DOMAIN, VACUUM_ENTITY_ID
from .conftest import setup_integration

VACUUM_UNIQUE_ID = "LR3C012345-litter_box"


async def test_vacuum(
    hass: HomeAssistant, entity_registry: er.EntityRegistry, mock_account: MagicMock
) -> None:
    """Tests the vacuum entity was set up."""
    entity_registry.async_get_or_create(
        VACUUM_DOMAIN,
        DOMAIN,
        VACUUM_UNIQUE_ID,
        suggested_object_id=VACUUM_ENTITY_ID.replace(VACUUM_DOMAIN, ""),
    )
    ent_reg_entry = entity_registry.async_get(VACUUM_ENTITY_ID)
    assert ent_reg_entry.unique_id == VACUUM_UNIQUE_ID

    await setup_integration(hass, mock_account, VACUUM_DOMAIN)
    assert hass.services.has_service(DOMAIN, SERVICE_SET_SLEEP_MODE)

    vacuum = hass.states.get(VACUUM_ENTITY_ID)
    assert vacuum
    assert vacuum.state == VacuumActivity.DOCKED

    ent_reg_entry = entity_registry.async_get(VACUUM_ENTITY_ID)
    assert ent_reg_entry.unique_id == VACUUM_UNIQUE_ID


async def test_no_robots(
    hass: HomeAssistant,
    entity_registry: er.EntityRegistry,
    mock_account_with_no_robots: MagicMock,
) -> None:
    """Tests the vacuum entity was set up."""
    entry = await setup_integration(hass, mock_account_with_no_robots, VACUUM_DOMAIN)

    assert len(entity_registry.entities) == 0

    assert await hass.config_entries.async_unload(entry.entry_id)
    await hass.async_block_till_done()


async def test_vacuum_with_error(
    hass: HomeAssistant, mock_account_with_error: MagicMock
) -> None:
    """Tests a vacuum entity with an error."""
    await setup_integration(hass, mock_account_with_error, VACUUM_DOMAIN)

    vacuum = hass.states.get(VACUUM_ENTITY_ID)
    assert vacuum
    assert vacuum.state == VacuumActivity.ERROR


@pytest.mark.parametrize(
    ("robot_data", "expected_state"),
    [
        ({"displayCode": "DC_CAT_DETECT"}, VacuumActivity.DOCKED),
        ({"isDFIFull": True}, VacuumActivity.ERROR),
        (
            {"robotCycleState": "CYCLE_STATE_CAT_DETECT"},
            VacuumActivity.PAUSED,
        ),
    ],
)
async def test_activities(
    hass: HomeAssistant,
    mock_account_with_litterrobot_4: MagicMock,
    robot_data: dict[str, str | bool],
    expected_state: str,
) -> None:
    """Test sending commands to the switch."""
    await setup_integration(hass, mock_account_with_litterrobot_4, VACUUM_DOMAIN)
    robot: Robot = mock_account_with_litterrobot_4.robots[0]
    robot._update_data(robot_data, partial=True)

    vacuum = hass.states.get(VACUUM_ENTITY_ID)
    assert vacuum
    assert vacuum.state == expected_state


@pytest.mark.parametrize(
    ("service_domain", "service", "command", "extra"),
    [
        (VACUUM_DOMAIN, SERVICE_START, "start_cleaning", None),
        (VACUUM_DOMAIN, SERVICE_STOP, "set_power_status", None),
        (
            DOMAIN,
            SERVICE_SET_SLEEP_MODE,
            "set_sleep_mode",
            {"data": {"enabled": True, "start_time": "22:30"}},
        ),
        (
            DOMAIN,
            SERVICE_SET_SLEEP_MODE,
            "set_sleep_mode",
            {"data": {"enabled": True}},
        ),
        (
            DOMAIN,
            SERVICE_SET_SLEEP_MODE,
            "set_sleep_mode",
            {"data": {"enabled": False}},
        ),
    ],
)
async def test_commands(
    hass: HomeAssistant,
    mock_account: MagicMock,
    caplog: pytest.LogCaptureFixture,
    service_domain: str,
    service: str,
    command: str,
    extra: dict[str, Any],
    issue_registry: ir.IssueRegistry,
) -> None:
    """Test sending commands to the vacuum."""
    await setup_integration(hass, mock_account, VACUUM_DOMAIN)

    vacuum = hass.states.get(VACUUM_ENTITY_ID)
    assert vacuum
    assert vacuum.state == VacuumActivity.DOCKED

    extra = extra or {}
    data = {ATTR_ENTITY_ID: VACUUM_ENTITY_ID, **extra.get("data", {})}
    issues = extra.get("issues", set())

    await hass.services.async_call(
        service_domain,
        service,
        data,
        blocking=True,
    )
    getattr(mock_account.robots[0], command).assert_called_once()

    assert set(issue_registry.issues.keys()) == issues
