"""Rendering what a tool did.

The block is written from four places and read from stored rows written by
earlier versions, so it has to render anything shaped roughly like an event --
and everything in it is third-party text.
"""

from __future__ import annotations

from lembas.web.templating import templates


def _render(*events, live: bool = False) -> str:
    return templates.get_template("chat/_tool_activity.html").render(
        {"tool_events": list(events), "live": live}
    )


def test_a_search_still_says_it_searched_the_web():
    html = _render(
        {
            "name": "web_search",
            "kind": "search",
            "query": "mallorn",
            "status": "ok",
            "results": [
                {
                    "title": "Mallorn",
                    "url": "https://a.test/m",
                    "host": "a.test",
                    "snippet": "A tree.",
                }
            ],
        }
    )
    assert "Searched the web for “mallorn”" in html
    assert '<a class="tool-result__title" href="https://a.test/m"' in html
    assert "1 result" in html


def test_a_library_tool_no_longer_claims_to_have_searched_the_web():
    """Stored rows predate `kind`, and every one of them used to render a globe
    and "Searched the web for <the note title>"."""
    html = _render({"name": "notes_search", "query": "shopping", "status": "ok", "results": []})
    assert "Searched the web" not in html
    assert "notes_search" in html


def test_a_custom_tool_is_named_and_its_host_shown():
    html = _render(
        {
            "name": "weather",
            "kind": "custom",
            "label": "Weather",
            "query": "city='Minas Tirith'",
            "detail": "GET api.test",
            "status": "ok",
            "results": [],
            "text": "Sunny.",
        }
    )
    assert "Weather" in html
    assert "GET api.test" in html
    assert "Sunny." in html


def test_a_tools_own_text_is_escaped_and_never_rendered_as_markdown():
    """Hard rule 6. A tool's reply is exactly as untrusted as a search result,
    and markdown is the one path allowed to emit HTML."""
    html = _render(
        {
            "name": "weather",
            "kind": "custom",
            "label": "Weather",
            "status": "ok",
            "results": [],
            "text": "<img src=x onerror=alert(1)> [click](javascript:alert(1))",
        }
    )
    assert "<img" not in html
    assert "&lt;img" in html
    # The markdown link is shown as the text it is, not turned into an anchor.
    assert "<a " not in html
    assert "[click](javascript:alert(1))" in html


def test_a_result_url_that_is_not_http_never_becomes_a_link():
    html = _render(
        {
            "name": "web_search",
            "kind": "search",
            "status": "ok",
            "results": [{"title": "Bad", "url": "javascript:alert(1)", "host": "", "snippet": ""}],
        }
    )
    assert "<a " not in html
    assert '<span class="tool-result__title">Bad</span>' in html


def test_a_result_with_no_url_at_all_does_not_explode():
    html = _render(
        {
            "name": "notes_search",
            "status": "ok",
            "results": [{"title": "A note", "id": "abc"}],
        }
    )
    assert "A note" in html


def test_a_failure_shows_its_reason():
    html = _render(
        {
            "name": "weather",
            "kind": "custom",
            "label": "Weather",
            "status": "error",
            "error": "HTTP 503",
            "results": [],
        }
    )
    assert "tool-activity--error" in html
    assert "Weather failed" in html
    assert "HTTP 503" in html
