"""Axis light platform tests."""

from typing import Any
from unittest.mock import patch

from axis.models.api import CONTEXT
import pytest
import respx
from syrupy import SnapshotAssertion

from homeassistant.components.light import ATTR_BRIGHTNESS, DOMAIN as LIGHT_DOMAIN
from homeassistant.const import (
    ATTR_ENTITY_ID,
    SERVICE_TURN_OFF,
    SERVICE_TURN_ON,
    STATE_OFF,
    Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er

from .conftest import ConfigEntryFactoryType, RtspEventMock
from .const import DEFAULT_HOST, NAME

from tests.common import snapshot_platform

API_DISCOVERY_LIGHT_CONTROL = {
    "id": "light-control",
    "version": "1.1",
    "name": "Light Control",
}


@pytest.fixture
def light_control_items() -> list[dict[str, Any]]:
    """Available lights."""
    return [
        {
            "lightID": "led0",
            "lightType": "IR",
            "enabled": True,
            "synchronizeDayNightMode": True,
            "lightState": False,
            "automaticIntensityMode": False,
            "automaticAngleOfIlluminationMode": False,
            "nrOfLEDs": 1,
            "error": False,
            "errorInfo": "",
        }
    ]


@pytest.fixture(autouse=True)
def light_control_fixture(light_control_items: list[dict[str, Any]]) -> None:
    """Light control mock response."""
    data = {
        "apiVersion": "1.1",
        "context": CONTEXT,
        "method": "getLightInformation",
        "data": {"items": light_control_items},
    }
    respx.post(
        f"http://{DEFAULT_HOST}:80/axis-cgi/lightcontrol.cgi",
        json={
            "apiVersion": "1.1",
            "context": CONTEXT,
            "method": "getLightInformation",
        },
    ).respond(
        json=data,
    )


@pytest.mark.parametrize("api_discovery_items", [API_DISCOVERY_LIGHT_CONTROL])
@pytest.mark.parametrize("light_control_items", [[]])
@pytest.mark.usefixtures("config_entry_setup")
async def test_no_light_entity_without_light_control_representation(
    hass: HomeAssistant,
    mock_rtsp_event: RtspEventMock,
) -> None:
    """Verify no lights entities get created without light control representation."""
    mock_rtsp_event(
        topic="tns1:Device/tnsaxis:Light/Status",
        data_type="state",
        data_value="ON",
        source_name="id",
        source_idx="0",
    )
    await hass.async_block_till_done()

    assert not hass.states.async_entity_ids(LIGHT_DOMAIN)


@pytest.mark.parametrize("api_discovery_items", [API_DISCOVERY_LIGHT_CONTROL])
async def test_lights(
    hass: HomeAssistant,
    entity_registry: er.EntityRegistry,
    config_entry_factory: ConfigEntryFactoryType,
    mock_rtsp_event: RtspEventMock,
    snapshot: SnapshotAssertion,
) -> None:
    """Test that lights are loaded properly."""
    # Add light
    respx.post(
        f"http://{DEFAULT_HOST}:80/axis-cgi/lightcontrol.cgi",
        json={
            "apiVersion": "1.1",
            "context": CONTEXT,
            "method": "getCurrentIntensity",
            "params": {"lightID": "led0"},
        },
    ).respond(
        json={
            "apiVersion": "1.1",
            "context": "Axis library",
            "method": "getCurrentIntensity",
            "data": {"intensity": 100},
        },
    )
    respx.post(
        f"http://{DEFAULT_HOST}:80/axis-cgi/lightcontrol.cgi",
        json={
            "apiVersion": "1.1",
            "context": CONTEXT,
            "method": "getValidIntensity",
            "params": {"lightID": "led0"},
        },
    ).respond(
        json={
            "apiVersion": "1.1",
            "context": "Axis library",
            "method": "getValidIntensity",
            "data": {"ranges": [{"low": 0, "high": 150}]},
        },
    )

    with patch("homeassistant.components.axis.PLATFORMS", [Platform.LIGHT]):
        config_entry = await config_entry_factory()

    mock_rtsp_event(
        topic="tns1:Device/tnsaxis:Light/Status",
        data_type="state",
        data_value="ON",
        source_name="id",
        source_idx="0",
    )
    await hass.async_block_till_done()
    await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)

    entity_id = f"{LIGHT_DOMAIN}.{NAME}_ir_light_0"

    # Turn on, set brightness, light already on
    with (
        patch("axis.interfaces.vapix.LightHandler.activate_light") as mock_activate,
        patch(
            "axis.interfaces.vapix.LightHandler.set_manual_intensity"
        ) as mock_set_intensity,
    ):
        await hass.services.async_call(
            LIGHT_DOMAIN,
            SERVICE_TURN_ON,
            {ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 50},
            blocking=True,
        )
        mock_activate.assert_not_awaited()
        mock_set_intensity.assert_called_once_with("led0", 29)

    # Turn off
    with patch(
        "axis.interfaces.vapix.LightHandler.deactivate_light"
    ) as mock_deactivate:
        await hass.services.async_call(
            LIGHT_DOMAIN,
            SERVICE_TURN_OFF,
            {ATTR_ENTITY_ID: entity_id},
            blocking=True,
        )
        mock_deactivate.assert_called_once()

    # Event turn off light
    mock_rtsp_event(
        topic="tns1:Device/tnsaxis:Light/Status",
        data_type="state",
        data_value="OFF",
        source_name="id",
        source_idx="0",
    )
    await hass.async_block_till_done()

    light_0 = hass.states.get(entity_id)
    assert light_0.state == STATE_OFF

    # Turn on, set brightness
    with (
        patch("axis.interfaces.vapix.LightHandler.activate_light") as mock_activate,
        patch(
            "axis.interfaces.vapix.LightHandler.set_manual_intensity"
        ) as mock_set_intensity,
    ):
        await hass.services.async_call(
            LIGHT_DOMAIN,
            SERVICE_TURN_ON,
            {ATTR_ENTITY_ID: entity_id},
            blocking=True,
        )
        mock_activate.assert_called_once()
        mock_set_intensity.assert_not_called()

    # Turn off, light already off
    with patch(
        "axis.interfaces.vapix.LightHandler.deactivate_light"
    ) as mock_deactivate:
        await hass.services.async_call(
            LIGHT_DOMAIN,
            SERVICE_TURN_OFF,
            {ATTR_ENTITY_ID: entity_id},
            blocking=True,
        )
        mock_deactivate.assert_not_called()