from unittest.mock import MagicMock

import pytest

from messaging.rendering.telegram_markdown import (
    escape_md_v2,
    escape_md_v2_code,
    mdv2_bold,
    mdv2_code_inline,
    render_markdown_to_mdv2,
)
from messaging.transcript import RenderCtx, TranscriptBuffer


@pytest.fixture
def handler():
    platform = MagicMock()
    cli = MagicMock()
    store = MagicMock()
    return (platform, cli, store)


def _ctx() -> RenderCtx:
    return RenderCtx(
        bold=mdv2_bold,
        code_inline=mdv2_code_inline,
        escape_code=escape_md_v2_code,
        escape_text=escape_md_v2,
        render_markdown=render_markdown_to_mdv2,
    )


def test_transcript_structure_and_order(handler):
    """Verify ordered transcript rendering (thinking/tool/subagent/text/error/status)."""
    status = "✅ *Complete*"
    t = TranscriptBuffer()

    # Apply in a deliberate sequence.
    t.apply({"type": "thinking_chunk", "text": "Thinking process..."})
    t.apply(
        {"type": "tool_use", "id": "t1", "name": "list_files", "input": {"path": "."}}
    )

    # Subagent marker (Task tool).
    t.apply(
        {
            "type": "tool_use",
            "id": "task1",
            "name": "Task",
            "input": {"description": "Searching codebase..."},
        }
    )
    t.apply(
        {"type": "tool_use", "id": "t2", "name": "read_file", "input": {"path": "x.py"}}
    )
    t.apply({"type": "tool_result", "tool_use_id": "task1", "content": "done"})

    t.apply({"type": "text_chunk", "text": "Here is the file content."})
    t.apply({"type": "error", "message": "Some error happened"})

    msg = t.render(_ctx(), limit_chars=3900, status=status)

    print(f"Generated Message:\n{msg}")

    # Check existence
    assert "Thinking process..." in msg
    assert "list_files" in msg
    assert "read_file" in msg
    assert "Searching codebase..." in msg
    assert escape_md_v2("Here is the file content.") in msg
    assert "Some error happened" in msg
    assert "✅ *Complete*" in msg

    # Check headers/markers used in the transcript.
    assert "💭 *Thinking*" in msg
    assert "🛠 *Tool call:*" in msg
    assert "🤖 *Subagent:*" in msg
    assert "⚠️ *Error:*" in msg

    # Check Order: Thinking -> Tool call -> Subagent -> Content -> Errors -> Status
    p_thinking = msg.find("Thinking process...")
    p_tool_call = msg.find("🛠 *Tool call:*")
    p_subagent = msg.find("🤖 *Subagent:*")
    p_content = msg.find(escape_md_v2("Here is the file content."))
    p_errors = msg.find("⚠️ *Error:*")
    p_status = msg.find("✅ *Complete*")

    assert p_thinking < p_tool_call, "Thinking should come before tool calls"
    assert p_tool_call < p_subagent, "Tool calls should come before subagent marker"
    assert p_subagent < p_content, "Subagent should come before Content"
    assert p_content < p_errors, "Content should come before Errors"
    assert p_errors < p_status, "Errors should come before Status"


def test_transcript_simple(handler):
    """Verify simple transcript with just text + status."""
    t = TranscriptBuffer()
    t.apply({"type": "text_chunk", "text": "Simple message."})
    msg = t.render(_ctx(), limit_chars=3900, status="Ready")

    assert escape_md_v2("Simple message.") in msg
    assert "Ready" in msg
    assert "💭" not in msg
    assert "🛠" not in msg


def test_subagents_formatting(handler):
    """Verify subagent formatting (Task tool)."""
    t = TranscriptBuffer()
    t.apply(
        {
            "type": "tool_use",
            "id": "task_1",
            "name": "Task",
            "input": {"description": "Task 1"},
        }
    )
    t.apply({"type": "tool_result", "tool_use_id": "task_1", "content": "done"})
    t.apply(
        {
            "type": "tool_use",
            "id": "task_2",
            "name": "Task",
            "input": {"description": "Task 2"},
        }
    )

    msg = t.render(_ctx(), limit_chars=3900, status=None)

    assert "🤖 *Subagent:* `Task 1`" in msg
    assert "🤖 *Subagent:* `Task 2`" in msg
