"""Tests for Alexa Devices utils."""

from unittest.mock import AsyncMock

from aioamazondevices.const.devices import SPEAKER_GROUP_FAMILY
from aioamazondevices.exceptions import (
    CannotAuthenticate,
    CannotConnect,
    CannotRetrieveData,
)
import pytest

from homeassistant.components.alexa_devices.const import DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN, SERVICE_TURN_ON
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, entity_registry as er

from . import setup_integration
from .const import TEST_DEVICE_1_SN

from tests.common import MockConfigEntry

ENTITY_ID = "switch.echo_test_do_not_disturb"


@pytest.mark.parametrize(
    ("side_effect", "key", "error"),
    [
        pytest.param(
            CannotAuthenticate,
            "invalid_auth",
            "CannotAuthenticate()",
            id="cannot_authenticate",
        ),
        pytest.param(
            CannotConnect,
            "cannot_connect_with_error",
            "CannotConnect()",
            id="cannot_connect",
        ),
        pytest.param(
            CannotRetrieveData,
            "cannot_retrieve_data_with_error",
            "CannotRetrieveData()",
            id="cannot_retrieve_data",
        ),
        pytest.param(
            ValueError,
            "cannot_retrieve_data_with_error",
            "ValueError()",
            id="value_error",
        ),
    ],
)
async def test_alexa_api_call_exceptions(
    hass: HomeAssistant,
    mock_amazon_devices_client: AsyncMock,
    mock_config_entry: MockConfigEntry,
    side_effect: type[Exception],
    key: str,
    error: str,
) -> None:
    """Test alexa_api_call decorator for exceptions."""

    await setup_integration(hass, mock_config_entry)

    assert (state := hass.states.get(ENTITY_ID))
    assert state.state == STATE_OFF

    mock_amazon_devices_client.set_do_not_disturb.side_effect = side_effect

    # Call API
    with pytest.raises(HomeAssistantError) as exc_info:
        await hass.services.async_call(
            SWITCH_DOMAIN,
            SERVICE_TURN_ON,
            {ATTR_ENTITY_ID: ENTITY_ID},
            blocking=True,
        )

    assert exc_info.value.translation_domain == DOMAIN
    assert exc_info.value.translation_key == key
    assert exc_info.value.translation_placeholders == {"error": error}


async def test_alexa_unique_id_migration(
    hass: HomeAssistant,
    mock_amazon_devices_client: AsyncMock,
    mock_config_entry: MockConfigEntry,
    device_registry: dr.DeviceRegistry,
    entity_registry: er.EntityRegistry,
) -> None:
    """Test unique_id migration."""

    mock_config_entry.add_to_hass(hass)

    device = device_registry.async_get_or_create(
        config_entry_id=mock_config_entry.entry_id,
        identifiers={(DOMAIN, mock_config_entry.entry_id)},
        name=mock_config_entry.title,
        manufacturer="Amazon",
        model="Echo Dot",
        entry_type=dr.DeviceEntryType.SERVICE,
    )

    entity = entity_registry.async_get_or_create(
        Platform.SWITCH,
        DOMAIN,
        unique_id=f"{TEST_DEVICE_1_SN}-do_not_disturb",
        device_id=device.id,
        config_entry=mock_config_entry,
        has_entity_name=True,
    )

    await hass.config_entries.async_setup(mock_config_entry.entry_id)
    await hass.async_block_till_done()

    migrated_entity = entity_registry.async_get(entity.entity_id)
    assert migrated_entity is not None
    assert migrated_entity.config_entry_id == mock_config_entry.entry_id
    assert migrated_entity.unique_id == f"{TEST_DEVICE_1_SN}-dnd"


async def test_alexa_dnd_group_removal(
    hass: HomeAssistant,
    mock_amazon_devices_client: AsyncMock,
    mock_config_entry: MockConfigEntry,
    device_registry: dr.DeviceRegistry,
    entity_registry: er.EntityRegistry,
) -> None:
    """Test dnd switch is removed for Speaker Groups."""

    mock_config_entry.add_to_hass(hass)

    device = device_registry.async_get_or_create(
        config_entry_id=mock_config_entry.entry_id,
        identifiers={(DOMAIN, mock_config_entry.entry_id)},
        name=mock_config_entry.title,
        manufacturer="Amazon",
        model="Speaker Group",
        entry_type=dr.DeviceEntryType.SERVICE,
    )

    entity = entity_registry.async_get_or_create(
        Platform.SWITCH,
        DOMAIN,
        unique_id=f"{TEST_DEVICE_1_SN}-do_not_disturb",
        device_id=device.id,
        config_entry=mock_config_entry,
        has_entity_name=True,
    )

    mock_amazon_devices_client.get_devices_data.return_value[
        TEST_DEVICE_1_SN
    ].device_family = SPEAKER_GROUP_FAMILY

    await hass.config_entries.async_setup(mock_config_entry.entry_id)
    await hass.async_block_till_done()

    assert not hass.states.get(entity.entity_id)


async def test_alexa_unsupported_notification_sensor_removal(
    hass: HomeAssistant,
    mock_amazon_devices_client: AsyncMock,
    mock_config_entry: MockConfigEntry,
    device_registry: dr.DeviceRegistry,
    entity_registry: er.EntityRegistry,
) -> None:
    """Test notification sensors are removed from devices that do not support them."""

    mock_config_entry.add_to_hass(hass)

    device = device_registry.async_get_or_create(
        config_entry_id=mock_config_entry.entry_id,
        identifiers={(DOMAIN, mock_config_entry.entry_id)},
        name=mock_config_entry.title,
        manufacturer="Amazon",
        model="Speaker Group",
        entry_type=dr.DeviceEntryType.SERVICE,
    )

    entity = entity_registry.async_get_or_create(
        Platform.SENSOR,
        DOMAIN,
        unique_id=f"{TEST_DEVICE_1_SN}-Timer",
        device_id=device.id,
        config_entry=mock_config_entry,
        has_entity_name=True,
    )

    mock_amazon_devices_client.get_devices_data.return_value[
        TEST_DEVICE_1_SN
    ].notifications_supported = False

    await hass.config_entries.async_setup(mock_config_entry.entry_id)
    await hass.async_block_till_done()

    assert not hass.states.get(entity.entity_id)
