"""The tests for the  Template light platform."""

from typing import Any

import pytest
from syrupy.assertion import SnapshotAssertion

from homeassistant.components import light, template
from homeassistant.components.light import (
    ATTR_BRIGHTNESS,
    ATTR_COLOR_TEMP_KELVIN,
    ATTR_EFFECT,
    ATTR_HS_COLOR,
    ATTR_RGB_COLOR,
    ATTR_RGBW_COLOR,
    ATTR_RGBWW_COLOR,
    ATTR_TRANSITION,
    ColorMode,
    LightEntityFeature,
)
from homeassistant.const import (
    ATTR_ENTITY_ID,
    SERVICE_TURN_OFF,
    SERVICE_TURN_ON,
    STATE_OFF,
    STATE_ON,
    STATE_UNAVAILABLE,
    STATE_UNKNOWN,
)
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.typing import ConfigType

from .conftest import (
    ConfigurationStyle,
    TemplatePlatformSetup,
    assert_action,
    async_get_flow_preview_state,
    async_trigger,
    make_test_action,
    make_test_trigger,
    setup_and_test_nested_unique_id,
    setup_and_test_unique_id,
    setup_entity,
)

from tests.common import MockConfigEntry
from tests.typing import WebSocketGenerator

TEST_STATE_ENTITY_ID = "light.test_state"
TEST_AVAILABILITY_ENTITY = "binary_sensor.availability"

TEST_LIGHT = TemplatePlatformSetup(
    light.DOMAIN,
    "lights",
    "test_light",
    make_test_trigger(
        TEST_STATE_ENTITY_ID,
        TEST_AVAILABILITY_ENTITY,
    ),
)

ON_ACTION = make_test_action("turn_on")
OFF_ACTION = make_test_action("turn_off")
ON_OFF_ACTIONS = {
    **ON_ACTION,
    **OFF_ACTION,
}


BRIGHTNESS_DATA = {"brightness": "{{ brightness }}"}
SET_LEVEL_ACTION = make_test_action("set_level", BRIGHTNESS_DATA)
ON_OFF_SET_LEVEL_ACTIONS = {
    **ON_OFF_ACTIONS,
    **SET_LEVEL_ACTION,
}

COLOR_TEMP_ACTION = make_test_action(
    "set_temperature",
    {
        "color_temp": "{{color_temp}}",
        "color_temp_kelvin": "{{color_temp_kelvin}}",
    },
)
ON_OFF_COLOR_TEMP_ACTIONS = {
    **ON_OFF_ACTIONS,
    **COLOR_TEMP_ACTION,
}

HS_ACTION = make_test_action(
    "set_hs",
    {"s": "{{ s }}", "h": "{{ h }}"},
)
ON_OFF_HS_ACTIONS = {
    **ON_OFF_ACTIONS,
    **HS_ACTION,
}

RGB_ACTION = make_test_action(
    "set_rgb",
    {"r": "{{ r }}", "g": "{{ g }}", "b": "{{ b }}"},
)
ON_OFF_RGB_ACTIONS = {
    **ON_OFF_ACTIONS,
    **RGB_ACTION,
}

RGBW_ACTION = make_test_action(
    "set_rgbw",
    {"r": "{{ r }}", "g": "{{ g }}", "b": "{{ b }}", "w": "{{ w }}"},
)
ON_OFF_RGBW_ACTIONS = {
    **ON_OFF_ACTIONS,
    **RGBW_ACTION,
}

RGBWW_ACTION = make_test_action(
    "set_rgbww",
    {
        "r": "{{ r }}",
        "g": "{{ g }}",
        "b": "{{ b }}",
        "cw": "{{ cw }}",
        "ww": "{{ ww }}",
    },
)
ON_OFF_RGBWW_ACTIONS = {
    **ON_OFF_ACTIONS,
    **RGBWW_ACTION,
}

SET_EFFECT_ACTION = make_test_action("set_effect", {"effect": "{{ effect }}"})

TRANSITION_DATA = {"transition": "{{ transition }}"}
OFF_TRANSITION_ACTION = make_test_action("turn_off", TRANSITION_DATA)
ON_ACTION_WITH_TRANSITION = {
    **make_test_action("turn_on", TRANSITION_DATA),
    **OFF_ACTION,
    **make_test_action("set_level", {**BRIGHTNESS_DATA, **TRANSITION_DATA}),
}


OFF_ACTION_WITH_TRANSITION = {
    **ON_ACTION,
    **make_test_action("turn_off", TRANSITION_DATA),
    **make_test_action("set_level", {**BRIGHTNESS_DATA, **TRANSITION_DATA}),
}


ALL_COLOR_ACTIONS = {
    **HS_ACTION,
    **COLOR_TEMP_ACTION,
    **RGB_ACTION,
    **RGBW_ACTION,
    **RGBWW_ACTION,
}


async def _call_and_assert_action(
    hass: HomeAssistant,
    calls: list[ServiceCall],
    service: str,
    service_data: ConfigType | None = None,
    expected_data: ConfigType | None = None,
    expected_action: str | None = None,
) -> None:
    """Call a service and validate that it was called properly.

    The service is validated when expected_action is omitted.
    """
    if expected_action is None:
        expected_action = service
    current = len(calls)
    await hass.services.async_call(
        light.DOMAIN,
        service,
        {**(service_data or {}), ATTR_ENTITY_ID: TEST_LIGHT.entity_id},
        blocking=True,
    )
    assert_action(
        TEST_LIGHT, calls, current + 1, expected_action, **(expected_data or {})
    )


@pytest.fixture
async def setup_light(
    hass: HomeAssistant,
    count: int,
    style: ConfigurationStyle,
    config: dict[str, Any],
) -> None:
    """Do setup of light integration."""
    await setup_entity(hass, TEST_LIGHT, style, count, config)


@pytest.fixture
async def setup_state_light(
    hass: HomeAssistant,
    count: int,
    style: ConfigurationStyle,
    state_template: str,
    extra_config: ConfigType,
):
    """Do setup of light integration."""
    await setup_entity(
        hass,
        TEST_LIGHT,
        style,
        count,
        ON_OFF_SET_LEVEL_ACTIONS,
        state_template,
        extra_config,
    )


@pytest.fixture
async def setup_single_attribute_light(
    hass: HomeAssistant,
    count: int,
    style: ConfigurationStyle,
    attribute: str,
    attribute_template: str,
    extra_config: dict,
) -> None:
    """Do setup of light integration."""
    await setup_entity(
        hass,
        TEST_LIGHT,
        style,
        count,
        {attribute: attribute_template} if attribute and attribute_template else {},
        "{{ 1 == 1 }}",
        extra_config,
    )


@pytest.fixture
async def setup_single_action_light(
    hass: HomeAssistant,
    count: int,
    style: ConfigurationStyle,
    extra_config: dict,
) -> None:
    """Do setup of light integration."""
    await setup_entity(
        hass,
        TEST_LIGHT,
        style,
        count,
        extra_config,
    )


@pytest.fixture
async def setup_empty_action_light(
    hass: HomeAssistant,
    count: int,
    style: ConfigurationStyle,
    action: str,
    extra_config: dict,
) -> None:
    """Do setup of light integration."""
    await setup_entity(
        hass,
        TEST_LIGHT,
        style,
        count,
        {"turn_on": [], "turn_off": [], action: []},
        extra_config=extra_config,
    )


@pytest.fixture
async def setup_light_with_effects(
    hass: HomeAssistant,
    count: int,
    style: ConfigurationStyle,
    effect_list_template: str,
    effect_template: str,
) -> None:
    """Do setup of light with effects."""

    await setup_entity(
        hass,
        TEST_LIGHT,
        style,
        count,
        {
            **SET_EFFECT_ACTION,
            "effect_list": effect_list_template,
            "effect": effect_template,
        },
        "{{ true }}",
        ON_OFF_ACTIONS,
    )


@pytest.fixture
async def setup_light_with_mireds(
    hass: HomeAssistant,
    count: int,
    style: ConfigurationStyle,
    attribute: str,
    attribute_template: str,
) -> None:
    """Do setup of light that uses mireds."""
    await setup_entity(
        hass,
        TEST_LIGHT,
        style,
        count,
        {
            attribute: attribute_template,
            "temperature": "{{ 200 }}",
            **make_test_action("set_temperature", {"color_temp": "{{ color_temp }}"}),
        },
        "{{ 1==1 }}",
        ON_OFF_ACTIONS,
    )


@pytest.fixture
async def setup_light_with_transition_template(
    hass: HomeAssistant,
    count: int,
    style: ConfigurationStyle,
    transition_template: str,
) -> None:
    """Do setup of light that uses mireds."""
    await setup_entity(
        hass,
        TEST_LIGHT,
        style,
        count,
        {
            **SET_EFFECT_ACTION,
            "effect_list": "{{ ['Disco', 'Police'] }}",
            "effect": "{{ None }}",
            "supports_transition": transition_template,
        },
        "{{ 1==1 }}",
        ON_OFF_ACTIONS,
    )


@pytest.mark.parametrize(
    ("count", "state_template", "style", "extra_config"),
    [(1, "{{ states('sensor.test_state') }}", ConfigurationStyle.LEGACY, {})],
)
@pytest.mark.usefixtures("setup_state_light")
async def test_legacy_template_creates_warning(
    hass: HomeAssistant, caplog_setup_text
) -> None:
    """Test legacy YAML configuration logs a warning."""
    assert len(hass.states.async_all("light")) == 0
    assert "entities can only be configured under template:" in caplog_setup_text


@pytest.mark.parametrize(
    ("count", "state_template", "extra_config"),
    [(1, "{{states.test['big.fat...']}}", {})],
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_state_light")
async def test_template_state_invalid(hass: HomeAssistant) -> None:
    """Test template state with render error."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, None)

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_UNAVAILABLE
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(
    ("count", "state_template", "extra_config"),
    [(1, "{{ states.light.test_state.state }}", {})],
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_state_light")
async def test_template_state_text(hass: HomeAssistant) -> None:
    """Test the state text of a template."""
    set_state = STATE_ON
    await async_trigger(hass, TEST_STATE_ENTITY_ID, set_state)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == set_state
    assert state.attributes["color_mode"] == ColorMode.BRIGHTNESS
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0

    set_state = STATE_OFF
    await async_trigger(hass, TEST_STATE_ENTITY_ID, set_state)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == set_state
    assert state.attributes["color_mode"] is None
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(("count", "extra_config"), [(1, {})])
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.parametrize(
    ("state_template", "expected_state", "expected_color_mode"),
    [
        (
            "{{ 1 == 1 }}",
            STATE_ON,
            ColorMode.BRIGHTNESS,
        ),
        (
            "{{ 1 == 2 }}",
            STATE_OFF,
            None,
        ),
    ],
)
@pytest.mark.usefixtures("setup_state_light")
async def test_template_state_boolean(
    hass: HomeAssistant,
    expected_color_mode: ColorMode | None,
    expected_state: str,
) -> None:
    """Test the setting of the state with boolean on."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, expected_state)

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == expected_state
    assert state.attributes.get("color_mode") == expected_color_mode
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(
    ("count", "state_template", "extra_config"), [(0, "{%- if false -%}", {})]
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_state_light")
async def test_template_config_errors(hass: HomeAssistant) -> None:
    """Test template light configuration errors."""
    assert hass.states.async_all("light") == []


@pytest.mark.parametrize(
    ("count", "config"),
    [(0, {**ON_ACTION, **SET_LEVEL_ACTION})],
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_light")
async def test_missing_key(hass: HomeAssistant) -> None:
    """Test missing template."""
    assert hass.states.async_all("light") == []


@pytest.mark.parametrize(
    ("count", "state_template", "extra_config"),
    [(1, "{{ states.light.test_state.state }}", {})],
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_state_light")
async def test_on_action(hass: HomeAssistant, calls: list[ServiceCall]) -> None:
    """Test on action."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_OFF)

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_OFF
    assert state.attributes["color_mode"] is None
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(hass, calls, SERVICE_TURN_ON)

    assert state.state == STATE_OFF
    assert state.attributes["color_mode"] is None
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(
    ("config", "style"),
    [
        (
            {
                "state": "{{states.light.test_state.state}}",
                **ON_ACTION_WITH_TRANSITION,
                "supports_transition": "{{true}}",
            },
            ConfigurationStyle.MODERN,
        ),
        (
            {
                "state": "{{states.light.test_state.state}}",
                **ON_ACTION_WITH_TRANSITION,
                "supports_transition": "{{true}}",
            },
            ConfigurationStyle.TRIGGER,
        ),
    ],
)
@pytest.mark.usefixtures("setup_light")
async def test_on_action_with_transition(
    hass: HomeAssistant, calls: list[ServiceCall]
) -> None:
    """Test on action with transition."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_OFF)

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_OFF
    assert state.attributes["color_mode"] is None
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == LightEntityFeature.TRANSITION

    await _call_and_assert_action(
        hass, calls, SERVICE_TURN_ON, {ATTR_TRANSITION: 5}, {ATTR_TRANSITION: 5}
    )

    assert state.state == STATE_OFF
    assert state.attributes["color_mode"] is None
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == LightEntityFeature.TRANSITION


@pytest.mark.parametrize(("count", "config"), [(1, ON_OFF_SET_LEVEL_ACTIONS)])
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_light")
async def test_on_action_optimistic(
    hass: HomeAssistant, calls: list[ServiceCall]
) -> None:
    """Test on action with optimistic state."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_OFF)

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_UNKNOWN
    assert state.attributes["color_mode"] is None
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(hass, calls, SERVICE_TURN_ON)

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == ColorMode.BRIGHTNESS
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_BRIGHTNESS: 100},
        {ATTR_BRIGHTNESS: 100},
        "set_level",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == ColorMode.BRIGHTNESS
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(
    ("count", "state_template", "extra_config"),
    [(1, "{{ states.light.test_state.state }}", {})],
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_state_light")
async def test_off_action(hass: HomeAssistant, calls: list[ServiceCall]) -> None:
    """Test off action."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == ColorMode.BRIGHTNESS
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(hass, calls, SERVICE_TURN_OFF)

    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == ColorMode.BRIGHTNESS
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize("count", [(1)])
@pytest.mark.parametrize(
    ("config", "style"),
    [
        (
            {
                "state": "{{states.light.test_state.state}}",
                **OFF_ACTION_WITH_TRANSITION,
                "supports_transition": "{{true}}",
            },
            ConfigurationStyle.MODERN,
        ),
        (
            {
                "state": "{{states.light.test_state.state}}",
                **OFF_ACTION_WITH_TRANSITION,
                "supports_transition": "{{true}}",
            },
            ConfigurationStyle.TRIGGER,
        ),
    ],
)
@pytest.mark.usefixtures("setup_light")
async def test_off_action_with_transition(
    hass: HomeAssistant, calls: list[ServiceCall]
) -> None:
    """Test off action with transition."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == ColorMode.BRIGHTNESS
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == LightEntityFeature.TRANSITION

    await _call_and_assert_action(
        hass, calls, SERVICE_TURN_OFF, {ATTR_TRANSITION: 2}, {ATTR_TRANSITION: 2}
    )

    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == ColorMode.BRIGHTNESS
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == LightEntityFeature.TRANSITION


@pytest.mark.parametrize(("count", "config"), [(1, ON_OFF_SET_LEVEL_ACTIONS)])
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_light")
async def test_off_action_optimistic(
    hass: HomeAssistant, calls: list[ServiceCall]
) -> None:
    """Test off action with optimistic state."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_OFF)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_UNKNOWN
    assert state.attributes["color_mode"] is None
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(hass, calls, SERVICE_TURN_OFF)

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_OFF
    assert state.attributes["color_mode"] is None
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(
    ("count", "state_template", "extra_config"),
    [(1, "{{ 1 == 1 }}", {})],
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_state_light")
async def test_level_action_no_template(
    hass: HomeAssistant, calls: list[ServiceCall]
) -> None:
    """Test setting brightness with optimistic template."""
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("brightness") is None

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_BRIGHTNESS: 124},
        {ATTR_BRIGHTNESS: 124},
        "set_level",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_ON
    assert state.attributes["brightness"] == 124
    assert state.attributes["color_mode"] == ColorMode.BRIGHTNESS
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_SET_LEVEL_ACTIONS)])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "level"),
        (ConfigurationStyle.TRIGGER, "level"),
    ],
)
@pytest.mark.parametrize(
    ("expected_level", "attribute_template", "expected_color_mode"),
    [
        (255, "{{255}}", ColorMode.BRIGHTNESS),
        (None, "{{256}}", ColorMode.BRIGHTNESS),
        (None, "{{x - 12}}", ColorMode.BRIGHTNESS),
        (None, "{{ none }}", ColorMode.BRIGHTNESS),
        (None, "", ColorMode.BRIGHTNESS),
        (
            None,
            "{{ state_attr('light.nolight', 'brightness') }}",
            ColorMode.BRIGHTNESS,
        ),
        (None, "{{'one'}}", ColorMode.BRIGHTNESS),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_level_template(
    hass: HomeAssistant,
    expected_level: Any,
    expected_color_mode: ColorMode,
) -> None:
    """Test the template for the level."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("brightness") == expected_level
    assert state.state == STATE_ON

    assert state.attributes["color_mode"] == expected_color_mode
    assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_COLOR_TEMP_ACTIONS)])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "temperature"),
        (ConfigurationStyle.TRIGGER, "temperature"),
    ],
)
@pytest.mark.parametrize(
    ("expected_temp", "attribute_template", "expected_color_mode"),
    [
        (2000, "{{500}}", ColorMode.COLOR_TEMP),
        (None, "{{501}}", ColorMode.COLOR_TEMP),
        (None, "{{x - 12}}", ColorMode.COLOR_TEMP),
        (None, "None", ColorMode.COLOR_TEMP),
        (None, "{{ none }}", ColorMode.COLOR_TEMP),
        (None, "", ColorMode.COLOR_TEMP),
        (None, "{{ 'one' }}", ColorMode.COLOR_TEMP),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_temperature_template(
    hass: HomeAssistant,
    expected_temp: Any,
    expected_color_mode: ColorMode,
) -> None:
    """Test the template for the temperature."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("color_temp_kelvin") == expected_temp
    assert state.state == STATE_ON
    assert state.attributes.get("color_mode") == expected_color_mode
    assert state.attributes["supported_color_modes"] == [ColorMode.COLOR_TEMP]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_COLOR_TEMP_ACTIONS)])
@pytest.mark.parametrize(
    "style",
    [
        ConfigurationStyle.MODERN,
        ConfigurationStyle.TRIGGER,
    ],
)
@pytest.mark.usefixtures("setup_single_action_light")
async def test_temperature_action_no_template(
    hass: HomeAssistant,
    calls: list[ServiceCall],
) -> None:
    """Test setting temperature with optimistic template."""
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("color_template") is None

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_COLOR_TEMP_KELVIN: 2898},
        {ATTR_COLOR_TEMP_KELVIN: 2898},
        "set_temperature",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state is not None
    assert state.attributes.get("color_temp_kelvin") == 2898
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == ColorMode.COLOR_TEMP
    assert state.attributes["supported_color_modes"] == [ColorMode.COLOR_TEMP]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(
    ("count", "attribute_template", "extra_config"),
    [(1, "Template light", ON_OFF_SET_LEVEL_ACTIONS)],
)
@pytest.mark.parametrize(
    ("style", "attribute", "entity_id"),
    [
        (ConfigurationStyle.MODERN, "name", "light.template_light"),
        (ConfigurationStyle.TRIGGER, "name", "light.template_light"),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_friendly_name(hass: HomeAssistant, entity_id: str) -> None:
    """Test the accessibility of the friendly_name attribute."""

    state = hass.states.get(entity_id)
    assert state is not None

    assert state.attributes.get("friendly_name") == "Template light"


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_SET_LEVEL_ACTIONS)])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "icon"),
        (ConfigurationStyle.TRIGGER, "icon"),
    ],
)
@pytest.mark.parametrize(
    "attribute_template", ["{% if states.light.test_state.state %}mdi:check{% endif %}"]
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_icon_template(hass: HomeAssistant) -> None:
    """Test icon template."""
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("icon") in ("", None)

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)

    assert state.attributes["icon"] == "mdi:check"


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_SET_LEVEL_ACTIONS)])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "picture"),
        (ConfigurationStyle.TRIGGER, "picture"),
    ],
)
@pytest.mark.parametrize(
    "attribute_template",
    ["{% if states.light.test_state.state %}/local/light.png{% endif %}"],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_entity_picture_template(hass: HomeAssistant) -> None:
    """Test entity_picture template."""
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("entity_picture") in ("", None)

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["entity_picture"] == "/local/light.png"


@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.parametrize(
    (
        "extra_config",
        "attribute",
        "attribute_value",
        "expected_action",
        "expected_data",
        "expected_color_mode",
    ),
    [
        (
            ON_OFF_HS_ACTIONS,
            ATTR_HS_COLOR,
            (40, 50),
            "set_hs",
            {"h": 40, "s": 50},
            ColorMode.HS,
        ),
        (
            ON_OFF_RGB_ACTIONS,
            ATTR_RGB_COLOR,
            (160, 78, 192),
            "set_rgb",
            {"r": 160, "g": 78, "b": 192},
            ColorMode.RGB,
        ),
        (
            ON_OFF_RGBW_ACTIONS,
            ATTR_RGBW_COLOR,
            (160, 78, 192, 25),
            "set_rgbw",
            {"r": 160, "g": 78, "b": 192, "w": 25},
            ColorMode.RGBW,
        ),
        (
            ON_OFF_RGBWW_ACTIONS,
            ATTR_RGBWW_COLOR,
            (160, 78, 192, 25, 50),
            "set_rgbww",
            {"r": 160, "g": 78, "b": 192, "cw": 25, "ww": 50},
            ColorMode.RGBWW,
        ),
    ],
)
@pytest.mark.usefixtures("setup_single_action_light")
async def test_color_actions_no_template(
    hass: HomeAssistant,
    calls: list[ServiceCall],
    attribute: str,
    attribute_value: tuple[int | float, ...],
    expected_action: str,
    expected_data: dict[str, int | float],
    expected_color_mode: ColorMode,
) -> None:
    """Test setting colors with an optimistic template light."""
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get(attribute) is None

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {attribute: attribute_value},
        expected_data,
        expected_action,
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == expected_color_mode
    assert state.attributes.get(attribute) == attribute_value
    assert state.attributes["supported_color_modes"] == [expected_color_mode]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_HS_ACTIONS)])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "hs"),
        (ConfigurationStyle.TRIGGER, "hs"),
    ],
)
@pytest.mark.parametrize(
    ("expected_hs", "attribute_template", "expected_color_mode"),
    [
        ((360, 100), "{{(360, 100)}}", ColorMode.HS),
        ((360, 100), "(360, 100)", ColorMode.HS),
        ((359.9, 99.9), "{{(359.9, 99.9)}}", ColorMode.HS),
        (None, "{{(361, 100)}}", ColorMode.HS),
        (None, "{{(360, 101)}}", ColorMode.HS),
        (None, "[{{(360)}},{{null}}]", ColorMode.HS),
        (None, "{{x - 12}}", ColorMode.HS),
        (None, "", ColorMode.HS),
        (None, "{{ none }}", ColorMode.HS),
        (None, "{{('one','two')}}", ColorMode.HS),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_hs_template(
    hass: HomeAssistant,
    expected_hs: tuple[float, float] | None,
    expected_color_mode: ColorMode,
) -> None:
    """Test the template for the color."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("hs_color") == expected_hs
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == expected_color_mode
    assert state.attributes["supported_color_modes"] == [ColorMode.HS]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_RGB_ACTIONS)])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "rgb"),
        (ConfigurationStyle.TRIGGER, "rgb"),
    ],
)
@pytest.mark.parametrize(
    ("expected_rgb", "attribute_template", "expected_color_mode"),
    [
        ((160, 78, 192), "{{(160, 78, 192)}}", ColorMode.RGB),
        ((160, 78, 192), "{{[160, 78, 192]}}", ColorMode.RGB),
        ((160, 78, 192), "(160, 78, 192)", ColorMode.RGB),
        ((159, 77, 191), "{{(159.9, 77.9, 191.9)}}", ColorMode.RGB),
        (None, "{{(256, 100, 100)}}", ColorMode.RGB),
        (None, "{{(100, 256, 100)}}", ColorMode.RGB),
        (None, "{{(100, 100, 256)}}", ColorMode.RGB),
        (None, "{{x - 12}}", ColorMode.RGB),
        (None, "", ColorMode.RGB),
        (None, "{{ none }}", ColorMode.RGB),
        (None, "{{('one','two','tree')}}", ColorMode.RGB),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_rgb_template(
    hass: HomeAssistant,
    expected_rgb: tuple[int, int, int] | None,
    expected_color_mode: ColorMode,
) -> None:
    """Test the template for the color."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("rgb_color") == expected_rgb
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == expected_color_mode
    assert state.attributes["supported_color_modes"] == [ColorMode.RGB]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_RGBW_ACTIONS)])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "rgbw"),
        (ConfigurationStyle.TRIGGER, "rgbw"),
    ],
)
@pytest.mark.parametrize(
    ("expected_rgbw", "attribute_template", "expected_color_mode"),
    [
        ((160, 78, 192, 25), "{{(160, 78, 192, 25)}}", ColorMode.RGBW),
        ((160, 78, 192, 25), "{{[160, 78, 192, 25]}}", ColorMode.RGBW),
        ((160, 78, 192, 25), "(160, 78, 192, 25)", ColorMode.RGBW),
        ((159, 77, 191, 24), "{{(159.9, 77.9, 191.9, 24.9)}}", ColorMode.RGBW),
        (None, "{{(256, 100, 100, 100)}}", ColorMode.RGBW),
        (None, "{{(100, 256, 100, 100)}}", ColorMode.RGBW),
        (None, "{{(100, 100, 256, 100)}}", ColorMode.RGBW),
        (None, "{{(100, 100, 100, 256)}}", ColorMode.RGBW),
        (None, "{{x - 12}}", ColorMode.RGBW),
        (None, "", ColorMode.RGBW),
        (None, "{{ none }}", ColorMode.RGBW),
        (None, "{{('one','two','tree','four')}}", ColorMode.RGBW),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_rgbw_template(
    hass: HomeAssistant,
    expected_rgbw: tuple[int, int, int, int] | None,
    expected_color_mode: ColorMode,
) -> None:
    """Test the template for the color."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("rgbw_color") == expected_rgbw
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == expected_color_mode
    assert state.attributes["supported_color_modes"] == [ColorMode.RGBW]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_RGBWW_ACTIONS)])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "rgbww"),
        (ConfigurationStyle.TRIGGER, "rgbww"),
    ],
)
@pytest.mark.parametrize(
    ("expected_rgbww", "attribute_template", "expected_color_mode"),
    [
        ((160, 78, 192, 25, 55), "{{(160, 78, 192, 25, 55)}}", ColorMode.RGBWW),
        ((160, 78, 192, 25, 55), "(160, 78, 192, 25, 55)", ColorMode.RGBWW),
        ((160, 78, 192, 25, 55), "{{[160, 78, 192, 25, 55]}}", ColorMode.RGBWW),
        (
            (159, 77, 191, 24, 54),
            "{{(159.9, 77.9, 191.9, 24.9, 54.9)}}",
            ColorMode.RGBWW,
        ),
        (None, "{{(256, 100, 100, 100, 100)}}", ColorMode.RGBWW),
        (None, "{{(100, 256, 100, 100, 100)}}", ColorMode.RGBWW),
        (None, "{{(100, 100, 256, 100, 100)}}", ColorMode.RGBWW),
        (None, "{{(100, 100, 100, 256, 100)}}", ColorMode.RGBWW),
        (None, "{{(100, 100, 100, 100, 256)}}", ColorMode.RGBWW),
        (None, "{{x - 12}}", ColorMode.RGBWW),
        (None, "", ColorMode.RGBWW),
        (None, "{{ none }}", ColorMode.RGBWW),
        (None, "{{('one','two','tree','four','five')}}", ColorMode.RGBWW),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_rgbww_template(
    hass: HomeAssistant,
    expected_rgbww: tuple[int, int, int, int, int] | None,
    expected_color_mode: ColorMode,
) -> None:
    """Test the template for the color."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("rgbww_color") == expected_rgbww
    assert state.state == STATE_ON
    assert state.attributes["color_mode"] == expected_color_mode
    assert state.attributes["supported_color_modes"] == [ColorMode.RGBWW]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(
    ("config", "style"),
    [
        (
            {
                **ON_OFF_ACTIONS,
                "state": "{{1 == 1}}",
                **ALL_COLOR_ACTIONS,
            },
            ConfigurationStyle.MODERN,
        ),
        (
            {
                **ON_OFF_ACTIONS,
                "state": "{{1 == 1}}",
                **ALL_COLOR_ACTIONS,
            },
            ConfigurationStyle.TRIGGER,
        ),
    ],
)
@pytest.mark.usefixtures("setup_light")
async def test_all_colors_mode_no_template(
    hass: HomeAssistant, calls: list[ServiceCall]
) -> None:
    """Test setting color and color temperature with optimistic template."""
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes.get("hs_color") is None

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_HS_COLOR: (40, 50)},
        {"h": 40, "s": 50},
        "set_hs",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["color_mode"] == ColorMode.HS
    assert state.attributes["color_temp_kelvin"] is None
    assert state.attributes["hs_color"] == (40, 50)
    assert state.attributes["supported_color_modes"] == [
        ColorMode.COLOR_TEMP,
        ColorMode.HS,
        ColorMode.RGB,
        ColorMode.RGBW,
        ColorMode.RGBWW,
    ]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_COLOR_TEMP_KELVIN: 8130},
        {ATTR_COLOR_TEMP_KELVIN: 8130, "color_temp": 123},
        "set_temperature",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["color_mode"] == ColorMode.COLOR_TEMP
    assert state.attributes["color_temp_kelvin"] == 8130
    assert "hs_color" in state.attributes  # Color temp represented as hs_color
    assert state.attributes["supported_color_modes"] == [
        ColorMode.COLOR_TEMP,
        ColorMode.HS,
        ColorMode.RGB,
        ColorMode.RGBW,
        ColorMode.RGBWW,
    ]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_RGB_COLOR: (160, 78, 192)},
        {"r": 160, "g": 78, "b": 192},
        "set_rgb",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["color_mode"] == ColorMode.RGB
    assert state.attributes["color_temp_kelvin"] is None
    assert state.attributes["rgb_color"] == (160, 78, 192)
    assert state.attributes["supported_color_modes"] == [
        ColorMode.COLOR_TEMP,
        ColorMode.HS,
        ColorMode.RGB,
        ColorMode.RGBW,
        ColorMode.RGBWW,
    ]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_RGBW_COLOR: (160, 78, 192, 25)},
        {"r": 160, "g": 78, "b": 192, "w": 25},
        "set_rgbw",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["color_mode"] == ColorMode.RGBW
    assert state.attributes["color_temp_kelvin"] is None
    assert state.attributes["rgbw_color"] == (160, 78, 192, 25)
    assert state.attributes["supported_color_modes"] == [
        ColorMode.COLOR_TEMP,
        ColorMode.HS,
        ColorMode.RGB,
        ColorMode.RGBW,
        ColorMode.RGBWW,
    ]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_RGBWW_COLOR: (160, 78, 192, 25, 55)},
        {"r": 160, "g": 78, "b": 192, "cw": 25, "ww": 55},
        "set_rgbww",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["color_mode"] == ColorMode.RGBWW
    assert state.attributes["color_temp_kelvin"] is None
    assert state.attributes["rgbww_color"] == (160, 78, 192, 25, 55)
    assert state.attributes["supported_color_modes"] == [
        ColorMode.COLOR_TEMP,
        ColorMode.HS,
        ColorMode.RGB,
        ColorMode.RGBW,
        ColorMode.RGBWW,
    ]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_HS_COLOR: (10, 20)},
        {"h": 10, "s": 20},
        "set_hs",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["color_mode"] == ColorMode.HS
    assert state.attributes["color_temp_kelvin"] is None
    assert state.attributes["hs_color"] == (10, 20)
    assert state.attributes["supported_color_modes"] == [
        ColorMode.COLOR_TEMP,
        ColorMode.HS,
        ColorMode.RGB,
        ColorMode.RGBW,
        ColorMode.RGBWW,
    ]
    assert state.attributes["supported_features"] == 0

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_COLOR_TEMP_KELVIN: 4273},
        {ATTR_COLOR_TEMP_KELVIN: 4273, "color_temp": 234},
        "set_temperature",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["color_mode"] == ColorMode.COLOR_TEMP
    assert state.attributes["color_temp_kelvin"] == 4273
    assert "hs_color" in state.attributes  # Color temp represented as hs_color
    assert state.attributes["supported_color_modes"] == [
        ColorMode.COLOR_TEMP,
        ColorMode.HS,
        ColorMode.RGB,
        ColorMode.RGBW,
        ColorMode.RGBWW,
    ]
    assert state.attributes["supported_features"] == 0


@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.parametrize(
    ("effect_list_template", "effect_template", "effect", "expected"),
    [
        ("{{ ['Disco', 'Police'] }}", "{{ 'Disco' }}", "Disco", "Disco"),
        ("{{ ['Disco', 'Police'] }}", "{{ 'None' }}", "RGB", None),
    ],
)
@pytest.mark.usefixtures("setup_light_with_effects")
async def test_effect_action(
    hass: HomeAssistant, effect: str, expected: Any, calls: list[ServiceCall]
) -> None:
    """Test setting valid effect with template."""

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state is not None

    await _call_and_assert_action(
        hass,
        calls,
        SERVICE_TURN_ON,
        {ATTR_EFFECT: effect},
        {ATTR_EFFECT: effect},
        "set_effect",
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state is not None
    assert state.attributes.get("effect") == expected


@pytest.mark.parametrize(("count", "effect_template"), [(1, "{{ None }}")])
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.parametrize(
    ("expected_effect_list", "effect_list_template"),
    [
        (
            ["Strobe color", "Police", "Christmas", "RGB", "Random Loop"],
            "{{ ['Strobe color', 'Police', 'Christmas', 'RGB', 'Random Loop'] }}",
        ),
        (
            ["Police", "RGB", "Random Loop"],
            "{{ ['Police', 'RGB', 'Random Loop'] }}",
        ),
        (None, "{{ [] }}"),
        (None, "{{ '[]' }}"),
        (None, "{{ 124 }}"),
        (None, "{{ '124' }}"),
        (None, "{{ none }}"),
        (None, ""),
    ],
)
@pytest.mark.usefixtures("setup_light_with_effects")
async def test_effect_list_template(
    hass: HomeAssistant, expected_effect_list: list[str] | None
) -> None:
    """Test the template for the effect list."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state is not None
    assert state.attributes.get("effect_list") == expected_effect_list


@pytest.mark.parametrize(
    ("count", "effect_list_template"),
    [(1, "{{ ['Strobe color', 'Police', 'Christmas', 'RGB', 'Random Loop'] }}")],
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.parametrize(
    ("expected_effect", "effect_template"),
    [
        (None, "Disco"),
        (None, "None"),
        (None, "{{ None }}"),
        ("Police", "Police"),
        ("Strobe color", "{{ 'Strobe color' }}"),
    ],
)
@pytest.mark.usefixtures("setup_light_with_effects")
async def test_effect_template(
    hass: HomeAssistant, expected_effect: str | None
) -> None:
    """Test the template for the effect."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state is not None
    assert state.attributes.get("effect") == expected_effect


@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "min_mireds"),
        (ConfigurationStyle.TRIGGER, "min_mireds"),
    ],
)
@pytest.mark.parametrize(
    ("expected_max_kelvin", "attribute_template"),
    [
        (8474, "{{118}}"),
        (6535, "{{x - 12}}"),
        (6535, "None"),
        (6535, "{{ none }}"),
        (6535, ""),
        (6535, "{{ 'a' }}"),
    ],
)
@pytest.mark.usefixtures("setup_light_with_mireds")
async def test_min_mireds_template(
    hass: HomeAssistant, expected_max_kelvin: int
) -> None:
    """Test the template for the min mireds."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state is not None
    assert state.attributes.get("max_color_temp_kelvin") == expected_max_kelvin


@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "max_mireds"),
        (ConfigurationStyle.TRIGGER, "max_mireds"),
    ],
)
@pytest.mark.parametrize(
    ("expected_min_kelvin", "attribute_template"),
    [
        (2049, "{{488}}"),
        (2000, "{{x - 12}}"),
        (2000, "None"),
        (2000, "{{ none }}"),
        (2000, ""),
        (2000, "{{ 'a' }}"),
    ],
)
@pytest.mark.usefixtures("setup_light_with_mireds")
async def test_max_mireds_template(
    hass: HomeAssistant,
    expected_min_kelvin: int,
) -> None:
    """Test the template for the max mireds."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state is not None
    assert state.attributes.get("min_color_temp_kelvin") == expected_min_kelvin


@pytest.mark.parametrize(("count", "extra_config"), [(1, ON_OFF_COLOR_TEMP_ACTIONS)])
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "supports_transition"),
        (ConfigurationStyle.TRIGGER, "supports_transition"),
    ],
)
@pytest.mark.parametrize(
    ("expected_supports_transition", "attribute_template"),
    [
        (True, "{{true}}"),
        (True, "{{1 == 1}}"),
        (False, "{{false}}"),
        (False, "{{ none }}"),
        (False, ""),
        (False, "None"),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_supports_transition_template(
    hass: HomeAssistant,
    expected_supports_transition: bool,
) -> None:
    """Test the template for the supports transition."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)

    state = hass.states.get(TEST_LIGHT.entity_id)

    expected_value = 1

    if expected_supports_transition is True:
        expected_value = 0

    assert state is not None
    assert (
        int(state.attributes.get("supported_features")) & LightEntityFeature.TRANSITION
    ) != expected_value


@pytest.mark.parametrize(
    ("count", "transition_template"), [(1, "{{ states('sensor.test') }}")]
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_light_with_transition_template")
async def test_supports_transition_template_updates(hass: HomeAssistant) -> None:
    """Test the template for the supports transition dynamically."""
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state is not None

    hass.states.async_set("sensor.test", 0)
    await hass.async_block_till_done()

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)

    state = hass.states.get(TEST_LIGHT.entity_id)
    supported_features = state.attributes.get("supported_features")
    assert supported_features == LightEntityFeature.EFFECT

    hass.states.async_set("sensor.test", 1)
    await hass.async_block_till_done()

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_OFF)

    state = hass.states.get(TEST_LIGHT.entity_id)
    supported_features = state.attributes.get("supported_features")
    assert (
        supported_features == LightEntityFeature.TRANSITION | LightEntityFeature.EFFECT
    )

    hass.states.async_set("sensor.test", 0)
    await hass.async_block_till_done()

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)

    state = hass.states.get(TEST_LIGHT.entity_id)
    supported_features = state.attributes.get("supported_features")
    assert supported_features == LightEntityFeature.EFFECT


@pytest.mark.parametrize(
    ("count", "extra_config", "attribute_template"),
    [
        (
            1,
            ON_OFF_SET_LEVEL_ACTIONS,
            "{{ is_state('binary_sensor.availability', 'on') }}",
        )
    ],
)
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "availability"),
        (ConfigurationStyle.TRIGGER, "availability"),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_available_template_with_entities(hass: HomeAssistant) -> None:
    """Test availability templates with values from other entities."""
    # When template returns true..
    hass.states.async_set(TEST_AVAILABILITY_ENTITY, STATE_ON)
    await hass.async_block_till_done()

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)

    # Device State should not be unavailable
    assert hass.states.get(TEST_LIGHT.entity_id).state != STATE_UNAVAILABLE

    # When Availability template returns false
    hass.states.async_set(TEST_AVAILABILITY_ENTITY, STATE_OFF)
    await hass.async_block_till_done()

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_OFF)

    # device state should be unavailable
    assert hass.states.get(TEST_LIGHT.entity_id).state == STATE_UNAVAILABLE


@pytest.mark.parametrize(
    ("count", "extra_config", "attribute_template"),
    [
        (
            1,
            ON_OFF_SET_LEVEL_ACTIONS,
            "{{ x - 12 }}",
        )
    ],
)
@pytest.mark.parametrize(
    ("style", "attribute"),
    [
        (ConfigurationStyle.MODERN, "availability"),
    ],
)
@pytest.mark.usefixtures("setup_single_attribute_light")
async def test_invalid_availability_template_keeps_component_available(
    hass: HomeAssistant, caplog_setup_text
) -> None:
    """Test that an invalid availability keeps the device available."""
    assert hass.states.get(TEST_LIGHT.entity_id).state != STATE_UNAVAILABLE
    assert "UndefinedError: 'x' is undefined" in caplog_setup_text


@pytest.mark.parametrize("config", [ON_OFF_ACTIONS])
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
async def test_unique_id(
    hass: HomeAssistant, style: ConfigurationStyle, config: ConfigType
) -> None:
    """Test unique_id option only creates one light per id."""
    await setup_and_test_unique_id(hass, TEST_LIGHT, style, config)


@pytest.mark.parametrize("config", [ON_OFF_ACTIONS])
@pytest.mark.parametrize(
    "style", [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER]
)
async def test_nested_unique_id(
    hass: HomeAssistant,
    style: ConfigurationStyle,
    config: ConfigType,
    entity_registry: er.EntityRegistry,
) -> None:
    """Test a template unique_id propagates to light unique_ids."""
    await setup_and_test_nested_unique_id(
        hass, TEST_LIGHT, style, entity_registry, config
    )


@pytest.mark.parametrize(("count", "extra_config"), [(1, {})])
@pytest.mark.parametrize(
    "style",
    [
        ConfigurationStyle.MODERN,
    ],
)
@pytest.mark.parametrize(
    ("action", "color_mode"),
    [
        ("set_level", ColorMode.BRIGHTNESS),
        ("set_temperature", ColorMode.COLOR_TEMP),
        ("set_hs", ColorMode.HS),
        ("set_rgb", ColorMode.RGB),
        ("set_rgbw", ColorMode.RGBW),
        ("set_rgbww", ColorMode.RGBWW),
    ],
)
@pytest.mark.usefixtures("setup_empty_action_light")
async def test_empty_color_mode_action_config(
    hass: HomeAssistant, color_mode: ColorMode
) -> None:
    """Test empty actions for color mode actions."""
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["supported_color_modes"] == [color_mode]

    await hass.services.async_call(
        light.DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: TEST_LIGHT.entity_id},
        blocking=True,
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_ON

    await hass.services.async_call(
        light.DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: TEST_LIGHT.entity_id},
        blocking=True,
    )

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


@pytest.mark.parametrize(("count"), [1])
@pytest.mark.parametrize(
    ("style", "extra_config"),
    [
        (
            ConfigurationStyle.MODERN,
            {
                "effect_list": "{{ ['a'] }}",
                "effect": "{{ 'a' }}",
            },
        ),
    ],
)
@pytest.mark.usefixtures("setup_empty_action_light")
@pytest.mark.parametrize("action", ["set_effect"])
async def test_effect_with_empty_action(hass: HomeAssistant) -> None:
    """Test empty set_effect action."""
    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.attributes["supported_features"] == LightEntityFeature.EFFECT


@pytest.mark.parametrize(
    ("count", "config"),
    [
        (
            1,
            {
                "state": "{{ is_state('light.test_state', 'on') }}",
                "turn_on": [],
                "turn_off": [],
                "optimistic": True,
            },
        )
    ],
)
@pytest.mark.parametrize(
    "style",
    [ConfigurationStyle.MODERN, ConfigurationStyle.TRIGGER],
)
@pytest.mark.usefixtures("setup_light")
async def test_optimistic_option(hass: HomeAssistant) -> None:
    """Test optimistic yaml option."""
    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_OFF)

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

    await hass.services.async_call(
        light.DOMAIN,
        "turn_on",
        {"entity_id": TEST_LIGHT.entity_id},
        blocking=True,
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == STATE_ON

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_ON)

    await async_trigger(hass, TEST_STATE_ENTITY_ID, STATE_OFF)

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


@pytest.mark.parametrize(
    ("count", "config"),
    [
        (
            1,
            {
                "state": "{{ is_state('light.test_state', 'on') }}",
                "turn_on": [],
                "turn_off": [],
                "optimistic": False,
            },
        )
    ],
)
@pytest.mark.parametrize(
    ("style", "expected"),
    [
        (ConfigurationStyle.MODERN, STATE_OFF),
        (ConfigurationStyle.TRIGGER, STATE_UNKNOWN),
    ],
)
@pytest.mark.usefixtures("setup_light")
async def test_not_optimistic(hass: HomeAssistant, expected: str) -> None:
    """Test optimistic yaml option set to false."""
    await hass.services.async_call(
        light.DOMAIN,
        "turn_on",
        {"entity_id": TEST_LIGHT.entity_id},
        blocking=True,
    )

    state = hass.states.get(TEST_LIGHT.entity_id)
    assert state.state == expected


async def test_setup_config_entry(
    hass: HomeAssistant,
    snapshot: SnapshotAssertion,
) -> None:
    """Tests creating a light from a config entry."""

    hass.states.async_set(
        "sensor.test_sensor",
        "on",
        {},
    )

    template_config_entry = MockConfigEntry(
        data={},
        domain=template.DOMAIN,
        options={
            "name": "My template",
            "state": "{{ states('sensor.test_sensor') }}",
            "turn_on": [],
            "turn_off": [],
            "template_type": light.DOMAIN,
        },
        title="My template",
    )
    template_config_entry.add_to_hass(hass)

    assert await hass.config_entries.async_setup(template_config_entry.entry_id)
    await hass.async_block_till_done()

    state = hass.states.get("light.my_template")
    assert state is not None
    assert state == snapshot


async def test_flow_preview(
    hass: HomeAssistant,
    hass_ws_client: WebSocketGenerator,
) -> None:
    """Test the config flow preview."""

    state = await async_get_flow_preview_state(
        hass,
        hass_ws_client,
        light.DOMAIN,
        {
            "name": "My template",
            "state": "{{ 'on' }}",
            "turn_on": [],
            "turn_off": [],
        },
    )

    assert state["state"] == STATE_ON
