"""Test string template extension."""

from homeassistant.core import HomeAssistant

from tests.helpers.template.helpers import render


def test_ordinal(hass: HomeAssistant) -> None:
    """Test the ordinal filter."""
    tests = [
        (1, "1st"),
        (2, "2nd"),
        (3, "3rd"),
        (4, "4th"),
        (5, "5th"),
        (12, "12th"),
        (100, "100th"),
        (101, "101st"),
    ]

    for value, expected in tests:
        assert render(hass, f"{{{{ {value} | ordinal }}}}") == expected


def test_slugify(hass: HomeAssistant) -> None:
    """Test the slugify filter."""
    # Test as global function
    assert render(hass, '{{ slugify("Home Assistant") }}') == "home_assistant"

    # Test as filter
    assert render(hass, '{{ "Home Assistant" | slugify }}') == "home_assistant"

    # Test with custom separator as global
    assert render(hass, '{{ slugify("Home Assistant", "-") }}') == "home-assistant"

    # Test with custom separator as filter
    assert render(hass, '{{ "Home Assistant" | slugify("-") }}') == "home-assistant"


def test_urlencode(hass: HomeAssistant) -> None:
    """Test the urlencode method."""
    # Test with dictionary

    result = render(
        hass, "{% set dict = {'foo': 'x&y', 'bar': 42} %}{{ dict | urlencode }}"
    )
    assert result == "foo=x%26y&bar=42"

    # Test with string

    result = render(
        hass, "{% set string = 'the quick brown fox = true' %}{{ string | urlencode }}"
    )
    assert result == "the%20quick%20brown%20fox%20%3D%20true"


def test_string_functions_with_non_string_input(hass: HomeAssistant) -> None:
    """Test string functions with non-string input (automatic conversion)."""
    # Test ordinal with integer
    assert render(hass, "{{ 42 | ordinal }}") == "42nd"

    # Test slugify with integer - Note: Jinja2 may return integer for simple cases
    result = render(hass, "{{ 123 | slugify }}")
    # Accept either string or integer result for simple numeric cases
    assert result in ["123", 123]


def test_ordinal_edge_cases(hass: HomeAssistant) -> None:
    """Test ordinal function with edge cases."""
    # Test teens (11th, 12th, 13th should all be 'th')
    teens_tests = [
        (11, "11th"),
        (12, "12th"),
        (13, "13th"),
        (111, "111th"),
        (112, "112th"),
        (113, "113th"),
    ]

    for value, expected in teens_tests:
        assert render(hass, f"{{{{ {value} | ordinal }}}}") == expected

    # Test other numbers ending in 1, 2, 3
    other_tests = [
        (21, "21st"),
        (22, "22nd"),
        (23, "23rd"),
        (121, "121st"),
        (122, "122nd"),
        (123, "123rd"),
    ]

    for value, expected in other_tests:
        assert render(hass, f"{{{{ {value} | ordinal }}}}") == expected


def test_slugify_various_separators(hass: HomeAssistant) -> None:
    """Test slugify with various separators."""
    test_cases = [
        ("Hello World", "_", "hello_world"),
        ("Hello World", "-", "hello-world"),
        ("Hello World", ".", "hello.world"),
        ("Hello-World_Test", "~", "hello~world~test"),
    ]

    for text, separator, expected in test_cases:
        # Test as global function
        assert render(hass, f'{{{{ slugify("{text}", "{separator}") }}}}') == expected

        # Test as filter
        assert render(hass, f'{{{{ "{text}" | slugify("{separator}") }}}}') == expected


def test_urlencode_various_types(hass: HomeAssistant) -> None:
    """Test urlencode with various data types."""
    # Test with nested dictionary values
    result = render(
        hass,
        "{% set data = {'key': 'value with spaces', 'num': 123} %}"
        "{{ data | urlencode }}",
    )
    # URL encoding can have different order, so check both parts are present
    # Note: urllib.parse.urlencode uses + for spaces in form data
    assert "key=value+with+spaces" in result
    assert "num=123" in result

    # Test with special characters

    result = render(
        hass, "{% set data = {'special': 'a+b=c&d'} %}{{ data | urlencode }}"
    )
    assert result == "special=a%2Bb%3Dc%26d"
