"""Tests for Context dataclass."""


import pytest

from ai_qa.core.context import Context


def test_create_minimal_context() -> None:
    """Test creating context with only output field."""
    ctx = Context(output="Hello, world!")
    assert ctx.output == "Hello, world!"
    assert ctx.input is None
    assert ctx.ground_truth is None
    assert ctx.context is None
    assert ctx.tool_calls is None
    assert ctx.conversation is None
    assert ctx.metadata == {}


def test_create_full_context() -> None:
    """Test creating context with all fields populated."""
    ctx = Context(
        input="What is 2+2?",
        output="4",
        ground_truth="4",
        context=["2+2 = 4 (basic arithmetic)"],
        tool_calls=[{"name": "calculator", "arguments": {"x": 2, "y": 2}}],
        conversation=[
            {"role": "user", "content": "What is 2+2?"},
            {"role": "assistant", "content": "4"},
        ],
        metadata={"model": "claude-3", "temperature": 0.7},
    )
    assert ctx.input == "What is 2+2?"
    assert ctx.output == "4"
    assert ctx.ground_truth == "4"
    assert len(ctx.context) == 1
    assert len(ctx.tool_calls) == 1
    assert len(ctx.conversation) == 2
    assert ctx.metadata["model"] == "claude-3"


def test_context_is_immutable() -> None:
    """Test that Context is frozen (immutable)."""
    ctx = Context(output="test")
    with pytest.raises(Exception):  # Pydantic raises ValidationError
        ctx.output = "modified"


def test_context_output_required() -> None:
    """Test that None output raises ValidationError."""
    with pytest.raises(Exception):  # Pydantic raises ValidationError
        Context(output=None)


def test_context_conversation_validation() -> None:
    """Test that bad conversation format raises error."""
    # Missing role
    with pytest.raises(Exception):
        Context(
            output="test",
            conversation=[{"content": "hello"}],
        )

    # Missing content
    with pytest.raises(Exception):
        Context(
            output="test",
            conversation=[{"role": "user"}],
        )

    # Not a dict
    with pytest.raises(Exception):
        Context(
            output="test",
            conversation=["not a dict"],
        )


def test_context_tool_calls_validation() -> None:
    """Test that bad tool_calls format raises error."""
    # Missing name
    with pytest.raises(Exception):
        Context(
            output="test",
            tool_calls=[{"arguments": {}}],
        )

    # Not a dict
    with pytest.raises(Exception):
        Context(
            output="test",
            tool_calls=["not a dict"],
        )


def test_context_serialization() -> None:
    """Test that model_dump() round-trips correctly."""
    ctx1 = Context(
        input="test input",
        output="test output",
        ground_truth="expected",
        metadata={"key": "value"},
    )
    dumped = ctx1.model_dump()
    ctx2 = Context(**dumped)
    assert ctx2.input == ctx1.input
    assert ctx2.output == ctx1.output
    assert ctx2.ground_truth == ctx1.ground_truth
    assert ctx2.metadata == ctx1.metadata


def test_context_repr_truncates_long_strings() -> None:
    """Test that repr doesn't dump 10KB of text."""
    long_string = "x" * 1000
    ctx = Context(output=long_string)
    repr_str = repr(ctx)
    assert len(repr_str) < 500  # Should be much shorter than original
    assert "..." in repr_str


def test_context_metadata_must_be_serializable() -> None:
    """Test that non-serializable metadata raises error."""

    class NonSerializable:
        pass

    with pytest.raises(Exception):
        Context(output="test", metadata={"bad": NonSerializable()})


def test_context_supports_dict_and_list_outputs() -> None:
    """Test that output can be dict or list."""
    ctx_dict = Context(output={"key": "value"})
    assert ctx_dict.output == {"key": "value"}

    ctx_list = Context(output=["item1", "item2"])
    assert ctx_list.output == ["item1", "item2"]


def test_context_metadata_defaults_to_empty_dict() -> None:
    """Test that metadata defaults to empty dict."""
    ctx = Context(output="test")
    assert ctx.metadata == {}
    assert isinstance(ctx.metadata, dict)
