"""Axis light platform tests."""
from unittest.mock import patch

import pytest
import respx

from homeassistant.components.axis.const import DOMAIN as AXIS_DOMAIN
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,
    STATE_ON,
)
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component

from .const import DEFAULT_HOST, NAME

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


@pytest.fixture
def light_control_items():
    """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):
    """Light control mock response."""
    data = {
        "apiVersion": "1.1",
        "method": "getLightInformation",
        "data": {"items": light_control_items},
    }
    respx.post(f"http://{DEFAULT_HOST}:80/axis-cgi/lightcontrol.cgi").respond(
        json=data,
    )


async def test_platform_manually_configured(hass: HomeAssistant) -> None:
    """Test that nothing happens when platform is manually configured."""
    assert await async_setup_component(
        hass, LIGHT_DOMAIN, {LIGHT_DOMAIN: {"platform": AXIS_DOMAIN}}
    )

    assert AXIS_DOMAIN not in hass.data


async def test_no_lights(hass: HomeAssistant, setup_config_entry) -> None:
    """Test that no light events in Axis results in no light entities."""
    assert not hass.states.async_entity_ids(LIGHT_DOMAIN)


@pytest.mark.parametrize("api_discovery_items", [API_DISCOVERY_LIGHT_CONTROL])
@pytest.mark.parametrize("light_control_items", [[]])
async def test_no_light_entity_without_light_control_representation(
    hass: HomeAssistant, setup_config_entry, mock_rtsp_event
) -> 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, setup_config_entry, mock_rtsp_event) -> None:
    """Test that lights are loaded properly."""
    # Add light
    with patch(
        "axis.vapix.interfaces.light_control.LightControl.get_current_intensity",
        return_value={"data": {"intensity": 100}},
    ), patch(
        "axis.vapix.interfaces.light_control.LightControl.get_valid_intensity",
        return_value={"data": {"ranges": [{"high": 150}]}},
    ):
        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 len(hass.states.async_entity_ids(LIGHT_DOMAIN)) == 1

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

    light_0 = hass.states.get(entity_id)
    assert light_0.state == STATE_ON
    assert light_0.name == f"{NAME} IR Light 0"

    # Turn on, set brightness, light already on
    with patch(
        "axis.vapix.interfaces.light_control.LightControl.activate_light"
    ) as mock_activate, patch(
        "axis.vapix.interfaces.light_control.LightControl.set_manual_intensity"
    ) as mock_set_intensity, patch(
        "axis.vapix.interfaces.light_control.LightControl.get_current_intensity",
        return_value={"data": {"intensity": 100}},
    ):
        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.vapix.interfaces.light_control.LightControl.deactivate_light"
    ) as mock_deactivate, patch(
        "axis.vapix.interfaces.light_control.LightControl.get_current_intensity",
        return_value={"data": {"intensity": 100}},
    ):
        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.vapix.interfaces.light_control.LightControl.activate_light"
    ) as mock_activate, patch(
        "axis.vapix.interfaces.light_control.LightControl.set_manual_intensity"
    ) as mock_set_intensity, patch(
        "axis.vapix.interfaces.light_control.LightControl.get_current_intensity",
        return_value={"data": {"intensity": 100}},
    ):
        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.vapix.interfaces.light_control.LightControl.deactivate_light"
    ) as mock_deactivate, patch(
        "axis.vapix.interfaces.light_control.LightControl.get_current_intensity",
        return_value={"data": {"intensity": 100}},
    ):
        await hass.services.async_call(
            LIGHT_DOMAIN,
            SERVICE_TURN_OFF,
            {ATTR_ENTITY_ID: entity_id},
            blocking=True,
        )
        mock_deactivate.assert_not_called()