"""Tests for api/models/responses.py Pydantic response models."""

from api.models.anthropic import (
    ContentBlockText,
    ContentBlockThinking,
    ContentBlockToolUse,
)
from api.models.responses import MessagesResponse, TokenCountResponse, Usage


class TestUsage:
    """Tests for Usage model."""

    def test_required_fields(self):
        usage = Usage(input_tokens=10, output_tokens=20)
        assert usage.input_tokens == 10
        assert usage.output_tokens == 20

    def test_cache_defaults_zero(self):
        usage = Usage(input_tokens=1, output_tokens=2)
        assert usage.cache_creation_input_tokens == 0
        assert usage.cache_read_input_tokens == 0

    def test_cache_fields_set(self):
        usage = Usage(
            input_tokens=10,
            output_tokens=20,
            cache_creation_input_tokens=5,
            cache_read_input_tokens=3,
        )
        assert usage.cache_creation_input_tokens == 5
        assert usage.cache_read_input_tokens == 3

    def test_serialization(self):
        usage = Usage(input_tokens=10, output_tokens=20)
        data = usage.model_dump()
        assert data == {
            "input_tokens": 10,
            "output_tokens": 20,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0,
        }


class TestTokenCountResponse:
    """Tests for TokenCountResponse model."""

    def test_basic(self):
        resp = TokenCountResponse(input_tokens=42)
        assert resp.input_tokens == 42

    def test_serialization(self):
        resp = TokenCountResponse(input_tokens=100)
        data = resp.model_dump()
        assert data == {"input_tokens": 100}


class TestMessagesResponse:
    """Tests for MessagesResponse model."""

    def test_minimum_fields(self):
        resp = MessagesResponse(
            id="msg_001",
            model="test-model",
            content=[ContentBlockText(type="text", text="Hello")],
            usage=Usage(input_tokens=10, output_tokens=5),
        )
        assert resp.id == "msg_001"
        assert resp.model == "test-model"
        assert resp.role == "assistant"
        assert resp.type == "message"
        assert resp.stop_reason is None
        assert resp.stop_sequence is None

    def test_with_text_content(self):
        resp = MessagesResponse(
            id="msg_002",
            model="model",
            content=[ContentBlockText(type="text", text="response")],
            usage=Usage(input_tokens=1, output_tokens=1),
        )
        assert len(resp.content) == 1
        block = resp.content[0]
        assert isinstance(block, ContentBlockText)
        assert block.type == "text"
        assert block.text == "response"

    def test_with_tool_use_content(self):
        resp = MessagesResponse(
            id="msg_003",
            model="model",
            content=[
                ContentBlockToolUse(
                    type="tool_use",
                    id="tool_1",
                    name="Read",
                    input={"path": "test.py"},
                )
            ],
            usage=Usage(input_tokens=1, output_tokens=1),
            stop_reason="tool_use",
        )
        block = resp.content[0]
        assert isinstance(block, ContentBlockToolUse)
        assert block.type == "tool_use"
        assert block.name == "Read"
        assert resp.stop_reason == "tool_use"

    def test_with_thinking_content(self):
        resp = MessagesResponse(
            id="msg_004",
            model="model",
            content=[
                ContentBlockThinking(type="thinking", thinking="Let me reason..."),
                ContentBlockText(type="text", text="Answer"),
            ],
            usage=Usage(input_tokens=5, output_tokens=10),
        )
        assert len(resp.content) == 2
        block0 = resp.content[0]
        assert isinstance(block0, ContentBlockThinking)
        assert block0.type == "thinking"
        assert block0.thinking == "Let me reason..."
        block1 = resp.content[1]
        assert isinstance(block1, ContentBlockText)
        assert block1.type == "text"

    def test_with_all_content_types(self):
        resp = MessagesResponse(
            id="msg_005",
            model="model",
            content=[
                ContentBlockThinking(type="thinking", thinking="hmm"),
                ContentBlockText(type="text", text="result"),
                ContentBlockToolUse(
                    type="tool_use", id="t1", name="Bash", input={"command": "ls"}
                ),
            ],
            usage=Usage(input_tokens=10, output_tokens=20),
            stop_reason="tool_use",
        )
        assert len(resp.content) == 3

    def test_with_dict_content(self):
        """Dict content (unknown block type) should be accepted."""
        resp = MessagesResponse(
            id="msg_006",
            model="model",
            content=[{"type": "custom", "data": "value"}],
            usage=Usage(input_tokens=1, output_tokens=1),
        )
        block = resp.content[0]
        assert isinstance(block, dict)
        assert block["type"] == "custom"

    def test_stop_reason_values(self):
        """All valid stop_reason values should be accepted."""
        from typing import Literal

        reasons: list[
            Literal["end_turn", "max_tokens", "stop_sequence", "tool_use"]
        ] = [
            "end_turn",
            "max_tokens",
            "stop_sequence",
            "tool_use",
        ]
        for reason in reasons:
            resp = MessagesResponse(
                id="msg",
                model="model",
                content=[ContentBlockText(type="text", text="x")],
                usage=Usage(input_tokens=1, output_tokens=1),
                stop_reason=reason,
            )
            assert resp.stop_reason == reason

    def test_serialization_round_trip(self):
        resp = MessagesResponse(
            id="msg_rt",
            model="model-v1",
            content=[ContentBlockText(type="text", text="hello")],
            usage=Usage(input_tokens=10, output_tokens=5),
            stop_reason="end_turn",
        )
        data = resp.model_dump()
        restored = MessagesResponse(**data)
        assert restored.id == resp.id
        assert restored.model == resp.model
        assert restored.stop_reason == resp.stop_reason

    def test_empty_content_list(self):
        resp = MessagesResponse(
            id="msg_empty",
            model="model",
            content=[],
            usage=Usage(input_tokens=0, output_tokens=0),
        )
        assert resp.content == []
