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

from typing import Any

import pytest

from homeassistant import setup
from homeassistant.components.cover import ATTR_POSITION, ATTR_TILT_POSITION, DOMAIN
from homeassistant.const import (
    ATTR_ENTITY_ID,
    SERVICE_CLOSE_COVER,
    SERVICE_CLOSE_COVER_TILT,
    SERVICE_OPEN_COVER,
    SERVICE_OPEN_COVER_TILT,
    SERVICE_SET_COVER_POSITION,
    SERVICE_SET_COVER_TILT_POSITION,
    SERVICE_STOP_COVER,
    SERVICE_TOGGLE,
    SERVICE_TOGGLE_COVER_TILT,
    STATE_CLOSED,
    STATE_CLOSING,
    STATE_OFF,
    STATE_ON,
    STATE_OPEN,
    STATE_OPENING,
    STATE_UNAVAILABLE,
    STATE_UNKNOWN,
)
from homeassistant.core import HomeAssistant

from tests.common import assert_setup_component

ENTITY_COVER = "cover.test_template_cover"


OPEN_CLOSE_COVER_CONFIG = {
    "open_cover": {
        "service": "test.automation",
        "data_template": {
            "action": "open_cover",
            "caller": "{{ this.entity_id }}",
        },
    },
    "close_cover": {
        "service": "test.automation",
        "data_template": {
            "action": "close_cover",
            "caller": "{{ this.entity_id }}",
        },
    },
}


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    ("config", "states"),
    [
        (
            {
                DOMAIN: {
                    "platform": "template",
                    "covers": {
                        "test_template_cover": {
                            **OPEN_CLOSE_COVER_CONFIG,
                            "value_template": "{{ states.cover.test_state.state }}",
                        }
                    },
                }
            },
            [
                ("cover.test_state", STATE_OPEN, STATE_OPEN, {}, -1, ""),
                ("cover.test_state", STATE_CLOSED, STATE_CLOSED, {}, -1, ""),
                ("cover.test_state", STATE_OPENING, STATE_OPENING, {}, -1, ""),
                ("cover.test_state", STATE_CLOSING, STATE_CLOSING, {}, -1, ""),
                (
                    "cover.test_state",
                    "dog",
                    STATE_UNKNOWN,
                    {},
                    -1,
                    "Received invalid cover is_on state: dog",
                ),
                ("cover.test_state", STATE_OPEN, STATE_OPEN, {}, -1, ""),
                (
                    "cover.test_state",
                    "cat",
                    STATE_UNKNOWN,
                    {},
                    -1,
                    "Received invalid cover is_on state: cat",
                ),
                ("cover.test_state", STATE_CLOSED, STATE_CLOSED, {}, -1, ""),
                (
                    "cover.test_state",
                    "bear",
                    STATE_UNKNOWN,
                    {},
                    -1,
                    "Received invalid cover is_on state: bear",
                ),
            ],
        ),
        (
            {
                DOMAIN: {
                    "platform": "template",
                    "covers": {
                        "test_template_cover": {
                            **OPEN_CLOSE_COVER_CONFIG,
                            "position_template": (
                                "{{ states.cover.test.attributes.position }}"
                            ),
                            "value_template": "{{ states.cover.test_state.state }}",
                        }
                    },
                }
            },
            [
                ("cover.test_state", STATE_OPEN, STATE_UNKNOWN, {}, -1, ""),
                ("cover.test_state", STATE_CLOSED, STATE_UNKNOWN, {}, -1, ""),
                ("cover.test_state", STATE_OPENING, STATE_OPENING, {}, -1, ""),
                ("cover.test_state", STATE_CLOSING, STATE_CLOSING, {}, -1, ""),
                ("cover.test", STATE_CLOSED, STATE_CLOSING, {"position": 0}, 0, ""),
                ("cover.test_state", STATE_OPEN, STATE_CLOSED, {}, -1, ""),
                ("cover.test", STATE_CLOSED, STATE_OPEN, {"position": 10}, 10, ""),
                (
                    "cover.test_state",
                    "dog",
                    STATE_OPEN,
                    {},
                    -1,
                    "Received invalid cover is_on state: dog",
                ),
            ],
        ),
    ],
)
async def test_template_state_text(
    hass: HomeAssistant, states, start_ha, caplog: pytest.LogCaptureFixture
) -> None:
    """Test the state text of a template."""
    state = hass.states.get("cover.test_template_cover")
    assert state.state == STATE_UNKNOWN

    for entity, set_state, test_state, attr, pos, text in states:
        hass.states.async_set(entity, set_state, attributes=attr)
        await hass.async_block_till_done()
        state = hass.states.get("cover.test_template_cover")
        assert state.state == test_state
        if pos >= 0:
            assert state.attributes.get("current_position") == pos
        assert text in caplog.text


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    ("config", "entity", "set_state", "test_state", "attr"),
    [
        (
            {
                DOMAIN: {
                    "platform": "template",
                    "covers": {
                        "test_template_cover": {
                            **OPEN_CLOSE_COVER_CONFIG,
                            "position_template": (
                                "{{ states.cover.test.attributes.position }}"
                            ),
                            "value_template": "{{ states.cover.test_state.state }}",
                        }
                    },
                }
            },
            "cover.test_state",
            "",
            STATE_UNKNOWN,
            {},
        ),
        (
            {
                DOMAIN: {
                    "platform": "template",
                    "covers": {
                        "test_template_cover": {
                            **OPEN_CLOSE_COVER_CONFIG,
                            "position_template": (
                                "{{ states.cover.test.attributes.position }}"
                            ),
                            "value_template": "{{ states.cover.test_state.state }}",
                        }
                    },
                }
            },
            "cover.test_state",
            None,
            STATE_UNKNOWN,
            {},
        ),
    ],
)
async def test_template_state_text_ignored_if_none_or_empty(
    hass: HomeAssistant,
    entity: str,
    set_state: str,
    test_state: str,
    attr: dict[str, Any],
    start_ha,
    caplog: pytest.LogCaptureFixture,
) -> None:
    """Test ignoring an empty state text of a template."""
    state = hass.states.get("cover.test_template_cover")
    assert state.state == STATE_UNKNOWN

    hass.states.async_set(entity, set_state, attributes=attr)
    await hass.async_block_till_done()
    state = hass.states.get("cover.test_template_cover")
    assert state.state == test_state
    assert "ERROR" not in caplog.text


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "value_template": "{{ 1 == 1 }}",
                    }
                },
            }
        },
    ],
)
async def test_template_state_boolean(hass: HomeAssistant, start_ha) -> None:
    """Test the value_template attribute."""
    state = hass.states.get("cover.test_template_cover")
    assert state.state == STATE_OPEN


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "position_template": (
                            "{{ states.cover.test.attributes.position }}"
                        ),
                    }
                },
            }
        },
    ],
)
async def test_template_position(
    hass: HomeAssistant, start_ha, caplog: pytest.LogCaptureFixture
) -> None:
    """Test the position_template attribute."""
    hass.states.async_set("cover.test", STATE_OPEN)
    attrs = {}

    for set_state, pos, test_state in [
        (STATE_CLOSED, 42, STATE_OPEN),
        (STATE_OPEN, 0.0, STATE_CLOSED),
        (STATE_CLOSED, None, STATE_UNKNOWN),
    ]:
        attrs["position"] = pos
        hass.states.async_set("cover.test", set_state, attributes=attrs)
        await hass.async_block_till_done()
        state = hass.states.get("cover.test_template_cover")
        assert state.attributes.get("current_position") == pos
        assert state.state == test_state
        assert "ValueError" not in caplog.text


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "optimistic": False,
                    }
                },
            }
        },
    ],
)
async def test_template_not_optimistic(hass: HomeAssistant, start_ha) -> None:
    """Test the is_closed attribute."""
    state = hass.states.get("cover.test_template_cover")
    assert state.state == STATE_UNKNOWN


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    ("config", "tilt_position"),
    [
        (
            {
                DOMAIN: {
                    "platform": "template",
                    "covers": {
                        "test_template_cover": {
                            **OPEN_CLOSE_COVER_CONFIG,
                            "value_template": "{{ 1 == 1 }}",
                            "tilt_template": "{{ 42 }}",
                        }
                    },
                }
            },
            42.0,
        ),
        (
            {
                DOMAIN: {
                    "platform": "template",
                    "covers": {
                        "test_template_cover": {
                            **OPEN_CLOSE_COVER_CONFIG,
                            "value_template": "{{ 1 == 1 }}",
                            "tilt_template": "{{ None }}",
                        }
                    },
                }
            },
            None,
        ),
    ],
)
async def test_template_tilt(
    hass: HomeAssistant, tilt_position: float | None, start_ha
) -> None:
    """Test the tilt_template attribute."""
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_tilt_position") == tilt_position


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "position_template": "{{ -1 }}",
                        "tilt_template": "{{ 110 }}",
                    }
                },
            }
        },
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "position_template": "{{ on }}",
                        "tilt_template": (
                            "{% if states.cover.test_state.state %}"
                            "on"
                            "{% else %}"
                            "off"
                            "{% endif %}"
                        ),
                    },
                },
            }
        },
    ],
)
async def test_template_out_of_bounds(hass: HomeAssistant, start_ha) -> None:
    """Test template out-of-bounds condition."""
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_tilt_position") is None
    assert state.attributes.get("current_position") is None


@pytest.mark.parametrize(("count", "domain"), [(0, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {"test_template_cover": {"value_template": "{{ 1 == 1 }}"}},
            }
        },
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        "value_template": "{{ 1 == 1 }}",
                        "open_cover": {
                            "service": "test.automation",
                            "data_template": {
                                "action": "open_cover",
                                "caller": "{{ this.entity_id }}",
                            },
                        },
                    }
                },
            }
        },
    ],
)
async def test_template_open_or_position(
    hass: HomeAssistant, start_ha, caplog_setup_text
) -> None:
    """Test that at least one of open_cover or set_position is used."""
    assert hass.states.async_all("cover") == []
    assert "Invalid config for 'cover' from integration 'template'" in caplog_setup_text


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "position_template": "{{ 0 }}",
                    }
                },
            }
        },
    ],
)
async def test_open_action(hass: HomeAssistant, start_ha, calls) -> None:
    """Test the open_cover command."""
    state = hass.states.get("cover.test_template_cover")
    assert state.state == STATE_CLOSED

    await hass.services.async_call(
        DOMAIN, SERVICE_OPEN_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True
    )
    await hass.async_block_till_done()

    assert len(calls) == 1
    assert calls[0].data["action"] == "open_cover"
    assert calls[0].data["caller"] == "cover.test_template_cover"


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "position_template": "{{ 100 }}",
                        "stop_cover": {
                            "service": "test.automation",
                            "data_template": {
                                "action": "stop_cover",
                                "caller": "{{ this.entity_id }}",
                            },
                        },
                    }
                },
            }
        },
    ],
)
async def test_close_stop_action(hass: HomeAssistant, start_ha, calls) -> None:
    """Test the close-cover and stop_cover commands."""
    state = hass.states.get("cover.test_template_cover")
    assert state.state == STATE_OPEN

    await hass.services.async_call(
        DOMAIN, SERVICE_CLOSE_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True
    )
    await hass.async_block_till_done()

    await hass.services.async_call(
        DOMAIN, SERVICE_STOP_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True
    )
    await hass.async_block_till_done()

    assert len(calls) == 2
    assert calls[0].data["action"] == "close_cover"
    assert calls[0].data["caller"] == "cover.test_template_cover"
    assert calls[1].data["action"] == "stop_cover"
    assert calls[1].data["caller"] == "cover.test_template_cover"


@pytest.mark.parametrize(("count", "domain"), [(1, "input_number")])
@pytest.mark.parametrize(
    "config",
    [
        {"input_number": {"test": {"min": "0", "max": "100", "initial": "42"}}},
    ],
)
async def test_set_position(hass: HomeAssistant, start_ha, calls) -> None:
    """Test the set_position command."""
    with assert_setup_component(1, "cover"):
        assert await setup.async_setup_component(
            hass,
            "cover",
            {
                "cover": {
                    "platform": "template",
                    "covers": {
                        "test_template_cover": {
                            "set_cover_position": {
                                "service": "test.automation",
                                "data_template": {
                                    "action": "set_cover_position",
                                    "caller": "{{ this.entity_id }}",
                                    "position": "{{ position }}",
                                },
                            },
                        }
                    },
                }
            },
        )

    await hass.async_block_till_done()
    await hass.async_start()
    await hass.async_block_till_done()

    state = hass.states.async_set("input_number.test", 42)
    await hass.async_block_till_done()
    state = hass.states.get("cover.test_template_cover")
    assert state.state == STATE_UNKNOWN

    await hass.services.async_call(
        DOMAIN, SERVICE_OPEN_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True
    )
    await hass.async_block_till_done()
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_position") == 100.0
    assert len(calls) == 1
    assert calls[-1].data["action"] == "set_cover_position"
    assert calls[-1].data["caller"] == "cover.test_template_cover"
    assert calls[-1].data["position"] == 100

    await hass.services.async_call(
        DOMAIN, SERVICE_CLOSE_COVER, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True
    )
    await hass.async_block_till_done()
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_position") == 0.0
    assert len(calls) == 2
    assert calls[-1].data["action"] == "set_cover_position"
    assert calls[-1].data["caller"] == "cover.test_template_cover"
    assert calls[-1].data["position"] == 0

    await hass.services.async_call(
        DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True
    )
    await hass.async_block_till_done()
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_position") == 100.0
    assert len(calls) == 3
    assert calls[-1].data["action"] == "set_cover_position"
    assert calls[-1].data["caller"] == "cover.test_template_cover"
    assert calls[-1].data["position"] == 100

    await hass.services.async_call(
        DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True
    )
    await hass.async_block_till_done()
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_position") == 0.0
    assert len(calls) == 4
    assert calls[-1].data["action"] == "set_cover_position"
    assert calls[-1].data["caller"] == "cover.test_template_cover"
    assert calls[-1].data["position"] == 0

    await hass.services.async_call(
        DOMAIN,
        SERVICE_SET_COVER_POSITION,
        {ATTR_ENTITY_ID: ENTITY_COVER, ATTR_POSITION: 25},
        blocking=True,
    )
    await hass.async_block_till_done()
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_position") == 25.0
    assert len(calls) == 5
    assert calls[-1].data["action"] == "set_cover_position"
    assert calls[-1].data["caller"] == "cover.test_template_cover"
    assert calls[-1].data["position"] == 25


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "set_cover_tilt_position": {
                            "service": "test.automation",
                            "data_template": {
                                "action": "set_cover_tilt_position",
                                "caller": "{{ this.entity_id }}",
                                "tilt_position": "{{ tilt }}",
                            },
                        },
                    }
                },
            }
        },
    ],
)
@pytest.mark.parametrize(
    ("service", "attr", "tilt_position"),
    [
        (
            SERVICE_SET_COVER_TILT_POSITION,
            {ATTR_ENTITY_ID: ENTITY_COVER, ATTR_TILT_POSITION: 42},
            42,
        ),
        (SERVICE_OPEN_COVER_TILT, {ATTR_ENTITY_ID: ENTITY_COVER}, 100),
        (SERVICE_CLOSE_COVER_TILT, {ATTR_ENTITY_ID: ENTITY_COVER}, 0),
    ],
)
async def test_set_tilt_position(
    hass: HomeAssistant, service, attr, start_ha, calls, tilt_position
) -> None:
    """Test the set_tilt_position command."""
    await hass.services.async_call(
        DOMAIN,
        service,
        attr,
        blocking=True,
    )
    await hass.async_block_till_done()

    assert len(calls) == 1
    assert calls[-1].data["action"] == "set_cover_tilt_position"
    assert calls[-1].data["caller"] == "cover.test_template_cover"
    assert calls[-1].data["tilt_position"] == tilt_position


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        "set_cover_position": {"service": "test.automation"}
                    }
                },
            }
        },
    ],
)
async def test_set_position_optimistic(hass: HomeAssistant, start_ha, calls) -> None:
    """Test optimistic position mode."""
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_position") is None

    await hass.services.async_call(
        DOMAIN,
        SERVICE_SET_COVER_POSITION,
        {ATTR_ENTITY_ID: ENTITY_COVER, ATTR_POSITION: 42},
        blocking=True,
    )
    await hass.async_block_till_done()
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_position") == 42.0

    for service, test_state in [
        (SERVICE_CLOSE_COVER, STATE_CLOSED),
        (SERVICE_OPEN_COVER, STATE_OPEN),
        (SERVICE_TOGGLE, STATE_CLOSED),
        (SERVICE_TOGGLE, STATE_OPEN),
    ]:
        await hass.services.async_call(
            DOMAIN, service, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True
        )
        await hass.async_block_till_done()
        state = hass.states.get("cover.test_template_cover")
        assert state.state == test_state


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        "position_template": "{{ 100 }}",
                        "set_cover_position": {"service": "test.automation"},
                        "set_cover_tilt_position": {"service": "test.automation"},
                    }
                },
            }
        },
    ],
)
async def test_set_tilt_position_optimistic(
    hass: HomeAssistant, start_ha, calls
) -> None:
    """Test the optimistic tilt_position mode."""
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_tilt_position") is None

    await hass.services.async_call(
        DOMAIN,
        SERVICE_SET_COVER_TILT_POSITION,
        {ATTR_ENTITY_ID: ENTITY_COVER, ATTR_TILT_POSITION: 42},
        blocking=True,
    )
    await hass.async_block_till_done()
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("current_tilt_position") == 42.0

    for service, pos in [
        (SERVICE_CLOSE_COVER_TILT, 0.0),
        (SERVICE_OPEN_COVER_TILT, 100.0),
        (SERVICE_TOGGLE_COVER_TILT, 0.0),
        (SERVICE_TOGGLE_COVER_TILT, 100.0),
    ]:
        await hass.services.async_call(
            DOMAIN, service, {ATTR_ENTITY_ID: ENTITY_COVER}, blocking=True
        )
        await hass.async_block_till_done()
        state = hass.states.get("cover.test_template_cover")
        assert state.attributes.get("current_tilt_position") == pos


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "value_template": "{{ states.cover.test_state.state }}",
                        "icon_template": (
                            "{% if states.cover.test_state.state %}mdi:check{% endif %}"
                        ),
                    }
                },
            }
        },
    ],
)
async def test_icon_template(hass: HomeAssistant, start_ha) -> None:
    """Test icon template."""
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("icon") == ""

    state = hass.states.async_set("cover.test_state", STATE_OPEN)
    await hass.async_block_till_done()

    state = hass.states.get("cover.test_template_cover")

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


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "value_template": "{{ states.cover.test_state.state }}",
                        "entity_picture_template": (
                            "{% if states.cover.test_state.state %}"
                            "/local/cover.png"
                            "{% endif %}"
                        ),
                    }
                },
            }
        },
    ],
)
async def test_entity_picture_template(hass: HomeAssistant, start_ha) -> None:
    """Test icon template."""
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("entity_picture") == ""

    state = hass.states.async_set("cover.test_state", STATE_OPEN)
    await hass.async_block_till_done()

    state = hass.states.get("cover.test_template_cover")

    assert state.attributes["entity_picture"] == "/local/cover.png"


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "value_template": "open",
                        "availability_template": (
                            "{{ is_state('availability_state.state','on') }}"
                        ),
                    }
                },
            }
        },
    ],
)
async def test_availability_template(hass: HomeAssistant, start_ha) -> None:
    """Test availability template."""
    hass.states.async_set("availability_state.state", STATE_OFF)
    await hass.async_block_till_done()

    assert hass.states.get("cover.test_template_cover").state == STATE_UNAVAILABLE

    hass.states.async_set("availability_state.state", STATE_ON)
    await hass.async_block_till_done()

    assert hass.states.get("cover.test_template_cover").state != STATE_UNAVAILABLE


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "value_template": "open",
                    }
                },
            }
        },
    ],
)
async def test_availability_without_availability_template(
    hass: HomeAssistant, start_ha
) -> None:
    """Test that component is available if there is no."""
    state = hass.states.get("cover.test_template_cover")
    assert state.state != STATE_UNAVAILABLE


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "availability_template": "{{ x - 12 }}",
                        "value_template": "open",
                    }
                },
            }
        },
    ],
)
async def test_invalid_availability_template_keeps_component_available(
    hass: HomeAssistant, start_ha, caplog_setup_text
) -> None:
    """Test that an invalid availability keeps the device available."""
    assert hass.states.get("cover.test_template_cover") != STATE_UNAVAILABLE
    assert "UndefinedError: 'x' is undefined" in caplog_setup_text


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "value_template": "{{ states.cover.test_state.state }}",
                        "device_class": "door",
                    }
                },
            }
        },
    ],
)
async def test_device_class(hass: HomeAssistant, start_ha) -> None:
    """Test device class."""
    state = hass.states.get("cover.test_template_cover")
    assert state.attributes.get("device_class") == "door"


@pytest.mark.parametrize(("count", "domain"), [(0, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "value_template": "{{ states.cover.test_state.state }}",
                        "device_class": "barnacle_bill",
                    }
                },
            }
        },
    ],
)
async def test_invalid_device_class(hass: HomeAssistant, start_ha) -> None:
    """Test device class."""
    state = hass.states.get("cover.test_template_cover")
    assert not state


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "test_template_cover_01": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "unique_id": "not-so-unique-anymore",
                        "value_template": "{{ true }}",
                    },
                    "test_template_cover_02": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "unique_id": "not-so-unique-anymore",
                        "value_template": "{{ false }}",
                    },
                },
            }
        },
    ],
)
async def test_unique_id(hass: HomeAssistant, start_ha) -> None:
    """Test unique_id option only creates one cover per id."""
    assert len(hass.states.async_all()) == 1


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "garage_door": {
                        **OPEN_CLOSE_COVER_CONFIG,
                        "friendly_name": "Garage Door",
                        "value_template": (
                            "{{ is_state('binary_sensor.garage_door_sensor', 'off') }}"
                        ),
                    },
                },
            }
        },
    ],
)
async def test_state_gets_lowercased(hass: HomeAssistant, start_ha) -> None:
    """Test True/False is lowercased."""

    hass.states.async_set("binary_sensor.garage_door_sensor", "off")
    await hass.async_block_till_done()

    assert len(hass.states.async_all()) == 2

    assert hass.states.get("cover.garage_door").state == STATE_OPEN
    hass.states.async_set("binary_sensor.garage_door_sensor", "on")
    await hass.async_block_till_done()
    assert hass.states.get("cover.garage_door").state == STATE_CLOSED


@pytest.mark.parametrize(("count", "domain"), [(1, DOMAIN)])
@pytest.mark.parametrize(
    "config",
    [
        {
            DOMAIN: {
                "platform": "template",
                "covers": {
                    "office": {
                        "icon_template": """{% if is_state('cover.office', 'open') %}
            mdi:window-shutter-open
          {% else %}
            mdi:window-shutter
          {% endif %}""",
                        "open_cover": {
                            "service": "switch.turn_on",
                            "entity_id": "switch.office_blinds_up",
                        },
                        "close_cover": {
                            "service": "switch.turn_on",
                            "entity_id": "switch.office_blinds_down",
                        },
                        "stop_cover": {
                            "service": "switch.turn_on",
                            "entity_id": "switch.office_blinds_up",
                        },
                    },
                },
            }
        },
    ],
)
async def test_self_referencing_icon_with_no_template_is_not_a_loop(
    hass: HomeAssistant, start_ha, caplog: pytest.LogCaptureFixture
) -> None:
    """Test a self referencing icon with no value template is not a loop."""
    assert len(hass.states.async_all()) == 1

    assert "Template loop detected" not in caplog.text