"""Tests for button platform."""

import datetime
from unittest.mock import AsyncMock, patch

from aioautomower.exceptions import ApiError
from aioautomower.model import MowerAttributes
from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy.assertion import SnapshotAssertion

from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
from homeassistant.const import (
    ATTR_ENTITY_ID,
    STATE_UNAVAILABLE,
    STATE_UNKNOWN,
    Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er

from . import setup_integration
from .const import TEST_MOWER_ID

from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform


@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, tzinfo=datetime.UTC))
async def test_button_error_confirm(
    hass: HomeAssistant,
    mock_automower_client: AsyncMock,
    mock_config_entry: MockConfigEntry,
    freezer: FrozenDateTimeFactory,
    values: dict[str, MowerAttributes],
) -> None:
    """Test error confirm button command."""
    entity_id = "button.test_mower_1_confirm_error"
    await setup_integration(hass, mock_config_entry)
    state = hass.states.get(entity_id)
    assert state.name == "Test Mower 1 Confirm error"
    assert state.state == STATE_UNAVAILABLE

    values[TEST_MOWER_ID].mower.is_error_confirmable = None
    mock_automower_client.get_status.return_value = values
    freezer.tick(SCAN_INTERVAL)
    async_fire_time_changed(hass)
    await hass.async_block_till_done()
    state = hass.states.get(entity_id)
    assert state.state == STATE_UNAVAILABLE

    values[TEST_MOWER_ID].mower.is_error_confirmable = True
    mock_automower_client.get_status.return_value = values
    freezer.tick(SCAN_INTERVAL)
    async_fire_time_changed(hass)
    await hass.async_block_till_done()
    state = hass.states.get(entity_id)
    assert state.state == STATE_UNKNOWN


@pytest.mark.parametrize(
    ("entity_id", "name", "expected_command"),
    [
        (
            "button.test_mower_1_confirm_error",
            "Test Mower 1 Confirm error",
            "error_confirm",
        ),
        (
            "button.test_mower_1_sync_clock",
            "Test Mower 1 Sync clock",
            "set_datetime",
        ),
        (
            "button.test_mower_1_reset_cutting_blade_usage_time",
            "Test Mower 1 Reset cutting blade usage time",
            "reset_cutting_blade_usage_time",
        ),
    ],
)
@pytest.mark.freeze_time(datetime.datetime(2024, 2, 29, 11, tzinfo=datetime.UTC))
async def test_button_commands(
    hass: HomeAssistant,
    mock_automower_client: AsyncMock,
    mock_config_entry: MockConfigEntry,
    values: dict[str, MowerAttributes],
    entity_id: str,
    name: str,
    expected_command: str,
) -> None:
    """Test Automower button commands."""
    values[TEST_MOWER_ID].mower.is_error_confirmable = True
    await setup_integration(hass, mock_config_entry)

    state = hass.states.get(entity_id)
    assert state.name == name

    mock_automower_client.get_status.return_value = values

    await hass.services.async_call(
        BUTTON_DOMAIN,
        SERVICE_PRESS,
        {ATTR_ENTITY_ID: entity_id},
        blocking=True,
    )

    command_mock = getattr(mock_automower_client.commands, expected_command)
    command_mock.assert_called_once_with(TEST_MOWER_ID)

    await hass.async_block_till_done()
    state = hass.states.get(entity_id)
    assert state.state == "2024-02-29T11:00:00+00:00"
    command_mock.reset_mock()
    command_mock.side_effect = ApiError("Test error")
    with pytest.raises(
        HomeAssistantError,
        match="Failed to send command: Test error",
    ):
        await hass.services.async_call(
            BUTTON_DOMAIN,
            SERVICE_PRESS,
            {ATTR_ENTITY_ID: entity_id},
            blocking=True,
        )


@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_button_snapshot(
    hass: HomeAssistant,
    entity_registry: er.EntityRegistry,
    mock_automower_client: AsyncMock,
    mock_config_entry: MockConfigEntry,
    snapshot: SnapshotAssertion,
) -> None:
    """Snapshot tests of the button entities."""
    with patch(
        "homeassistant.components.husqvarna_automower.PLATFORMS",
        [Platform.BUTTON],
    ):
        await setup_integration(hass, mock_config_entry)
        await snapshot_platform(
            hass, entity_registry, snapshot, mock_config_entry.entry_id
        )
