"""Unit tests for `json_schema_to_pydantic`."""

import pytest
from mcp_chatkit_widget.schema_utils import json_schema_to_pydantic


class TestJsonSchemaToPydantic:
    """Tests for json_schema_to_pydantic function."""

    def test_non_object_schema_raises_error(self) -> None:
        """Test that non-object schemas raise ValueError (line 65)."""
        schema = {"type": "string"}
        with pytest.raises(ValueError, match="Root schema must be of type 'object'"):
            json_schema_to_pydantic(schema)

    def test_optional_field_conversion(self) -> None:
        """Test optional fields are converted with None default (lines 99-100)."""
        schema = {
            "type": "object",
            "properties": {
                "required_field": {"type": "string"},
                "optional_field": {"type": "string"},
            },
            "required": ["required_field"],
        }
        model = json_schema_to_pydantic(schema, "TestModel")

        # Create instance with only required field
        instance = model(required_field="test")
        assert instance.required_field == "test"
        assert instance.optional_field is None

        # Verify optional field can be set
        instance2 = model(required_field="test", optional_field="optional")
        assert instance2.optional_field == "optional"

    def test_schema_title_in_config(self) -> None:
        """Test custom schema title is used in model config (lines 106-107)."""
        schema = {
            "type": "object",
            "properties": {"name": {"type": "string"}},
        }
        model = json_schema_to_pydantic(schema, "TestModel", schema_title="CustomTitle")

        # Verify model config has custom title
        assert model.model_config.get("title") == "CustomTitle"


class TestComplexSchemaConversions:
    """Tests for complex schema scenarios."""

    def test_nested_object_with_optional_fields(self) -> None:
        """Test nested object schema with optional fields."""
        schema = {
            "type": "object",
            "properties": {
                "person": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "email": {"type": "string"},
                    },
                    "required": ["name"],
                },
            },
            "required": ["person"],
        }
        model = json_schema_to_pydantic(schema, "TestModel")

        # Create instance with nested optional field
        data = {"person": {"name": "Bob"}}
        instance = model(**data)
        assert instance.person.name == "Bob"  # type: ignore[attr-defined]
        assert instance.person.email is None  # type: ignore[attr-defined]

    def test_array_field_conversion(self) -> None:
        """Test array field conversion."""
        schema = {
            "type": "object",
            "properties": {
                "tags": {"type": "array"},
                "items": {"type": "string"},
            },
        }
        model = json_schema_to_pydantic(schema, "ArrayModel")

        data = {"tags": ["tag1", "tag2"], "items": "item1"}
        instance = model(**data)
        assert instance.tags == ["tag1", "tag2"]  # type: ignore[attr-defined]

    def test_array_items_type_mapping(self) -> None:
        """Test array items map to typed lists (lines 98-103)."""
        schema = {
            "type": "object",
            "properties": {
                "scores": {
                    "type": "array",
                    "items": {"type": "integer"},
                }
            },
            "required": ["scores"],
        }

        model = json_schema_to_pydantic(schema, "ScoreModel")

        instance = model(scores=[1, 2, 3])
        assert instance.scores == [1, 2, 3]  # type: ignore[attr-defined]

    def test_nested_array_falls_back_to_list_any(self) -> None:
        """Test nested arrays default to list[Any] (line 100)."""
        schema = {
            "type": "object",
            "properties": {
                "matrix": {
                    "type": "array",
                    "items": {
                        "type": "array",
                        "items": {"type": "integer"},
                    },
                }
            },
            "required": ["matrix"],
        }

        model = json_schema_to_pydantic(schema, "MatrixModel")

        instance = model(matrix=[[1, 2], [3, 4]])
        assert instance.matrix == [[1, 2], [3, 4]]  # type: ignore[attr-defined]
