"""Tests for TUI chat panel functionality.

Tests cover:
- Multi-line input (ChatInput widget)
- Markdown rendering with syntax highlighting
- Streaming display support
- Loading indicator
"""

import pytest

# Skip all tests if textual not available
pytest.importorskip("textual")

from cleave.tui.backends.base import Message, MessageType
from cleave.tui.widgets.chat_panel import ChatInput, ChatPanel


class TestChatInput:
    """Tests for the ChatInput widget (multi-line TextArea replacement)."""

    def test_chat_input_exists(self):
        """ChatInput class should be importable."""
        assert ChatInput is not None

    def test_chat_input_has_submit_callback(self):
        """ChatInput should have an on_submit callback attribute."""
        input_widget = ChatInput()
        assert hasattr(input_widget, "on_submit")

    def test_chat_input_line_numbers_disabled(self):
        """ChatInput should not show line numbers by default."""
        input_widget = ChatInput()
        assert input_widget.show_line_numbers is False


class TestChatPanel:
    """Tests for the ChatPanel widget."""

    def test_chat_panel_exists(self):
        """ChatPanel class should be importable."""
        assert ChatPanel is not None

    def test_chat_panel_has_streaming_methods(self):
        """ChatPanel should have streaming support methods."""
        # Check class has expected methods
        assert hasattr(ChatPanel, "start_streaming")
        assert hasattr(ChatPanel, "add_streaming_token")
        assert hasattr(ChatPanel, "finalize_streaming")

    def test_chat_panel_has_loading_method(self):
        """ChatPanel should have loading indicator control."""
        assert hasattr(ChatPanel, "set_loading")

    def test_chat_panel_has_markdown_rendering(self):
        """ChatPanel should have markdown rendering methods."""
        assert hasattr(ChatPanel, "_render_markdown")
        assert hasattr(ChatPanel, "_render_with_code_blocks")


class TestMessageType:
    """Tests for the MessageType enum and streaming support."""

    def test_message_type_values(self):
        """MessageType should have expected streaming values."""
        assert MessageType.COMPLETE.value == "complete"
        assert MessageType.STREAM_START.value == "stream_start"
        assert MessageType.STREAM_DELTA.value == "stream_delta"
        assert MessageType.STREAM_END.value == "stream_end"

    def test_message_is_streaming(self):
        """Message.is_streaming should detect streaming messages."""
        complete = Message(role="assistant", content="hello")
        assert complete.is_streaming is False

        stream_start = Message(
            role="assistant", content="", message_type=MessageType.STREAM_START
        )
        assert stream_start.is_streaming is True

        stream_delta = Message(
            role="assistant", content="tok", message_type=MessageType.STREAM_DELTA
        )
        assert stream_delta.is_streaming is True

        stream_end = Message(
            role="assistant", content="", message_type=MessageType.STREAM_END
        )
        assert stream_end.is_streaming is True


class TestMarkdownRendering:
    """Tests for markdown rendering logic."""

    def test_code_block_pattern(self):
        """Code block regex should match fenced code blocks."""
        import re

        pattern = r"```(\w*)\n(.*?)```"
        content = """Here is some code:

```python
def hello():
    print("world")
```

And more text."""

        matches = list(re.finditer(pattern, content, re.DOTALL))
        assert len(matches) == 1
        assert matches[0].group(1) == "python"
        assert "def hello():" in matches[0].group(2)

    def test_multiple_code_blocks(self):
        """Should handle multiple code blocks."""
        import re

        pattern = r"```(\w*)\n(.*?)```"
        content = """First:
```python
x = 1
```

Second:
```javascript
const y = 2;
```
"""
        matches = list(re.finditer(pattern, content, re.DOTALL))
        assert len(matches) == 2
        assert matches[0].group(1) == "python"
        assert matches[1].group(1) == "javascript"
