"""Tests for Pydantic models."""

import pytest
from pydantic import ValidationError

from midjourney_proxy_mcp.models import (
    ImageData,
    ImageListResponse,
    ImageRequest,
    ImageResponse,
    ImageStatus,
)


class TestImageRequest:
    """Tests for ImageRequest model."""

    def test_valid_request(self) -> None:
        """Test creating a valid image request."""
        request = ImageRequest(prompt="A beautiful sunset over the ocean")
        assert request.prompt == "A beautiful sunset over the ocean"
        assert request.ref is None

    def test_request_with_ref(self) -> None:
        """Test creating a request with reference ID."""
        request = ImageRequest(prompt="Test prompt", ref="my-ref-123")
        assert request.ref == "my-ref-123"

    def test_empty_prompt_fails(self) -> None:
        """Test that empty prompt is rejected."""
        with pytest.raises(ValidationError):
            ImageRequest(prompt="")

    def test_prompt_too_long_fails(self) -> None:
        """Test that prompt exceeding max length is rejected."""
        with pytest.raises(ValidationError):
            ImageRequest(prompt="x" * 4001)


class TestImageData:
    """Tests for ImageData model."""

    def test_minimal_data(self) -> None:
        """Test creating image data with minimal fields."""
        data = ImageData(
            id="123",
            prompt="Test prompt",
            status=ImageStatus.PENDING,
        )
        assert data.id == "123"
        assert data.status == ImageStatus.PENDING
        assert data.result is None

    def test_completed_data(self) -> None:
        """Test creating completed image data."""
        data = ImageData(
            id="456",
            prompt="Test prompt",
            status=ImageStatus.COMPLETED,
            result="https://example.com/image.png",
            upscaled_urls=["https://example.com/upscaled1.png"],
        )
        assert data.status == ImageStatus.COMPLETED
        assert data.result == "https://example.com/image.png"
        assert len(data.upscaled_urls or []) == 1

    def test_data_with_all_api_fields(self) -> None:
        """Test creating image data with all API response fields."""
        data = ImageData(
            id="789",
            prompt="Test prompt",
            status=ImageStatus.COMPLETED,
            result="https://example.com/image.png",
            url="https://example.com/image.png",
            results=None,
            progress=100,
            upscaled_urls=["https://example.com/upscaled1.png"],
            upscaled=["upscale-id-1"],
            ref="my-reference-id",
            error=None,
            user_created="user-123",
            date_created="2024-01-01T00:00:00Z",
        )
        assert data.url == "https://example.com/image.png"
        assert data.ref == "my-reference-id"
        assert data.user_created == "user-123"

    def test_progress_validation(self) -> None:
        """Test progress field validation (0-100 range)."""
        data = ImageData(
            id="123",
            prompt="Test",
            status=ImageStatus.IN_PROGRESS,
            progress=50,
        )
        assert data.progress == 50

    def test_progress_out_of_range_fails(self) -> None:
        """Test that progress > 100 is rejected."""
        with pytest.raises(ValidationError):
            ImageData(
                id="123",
                prompt="Test",
                status=ImageStatus.IN_PROGRESS,
                progress=101,
            )

    def test_flexible_type_coercion(self) -> None:
        """Test that response models accept type coercion from external API."""
        data = ImageData(
            id="123",
            prompt="Test",
            status="pending",  # type: ignore[arg-type]  # String instead of enum
        )
        assert data.status == ImageStatus.PENDING


class TestImageResponse:
    """Tests for ImageResponse model."""

    def test_response_wrapper(self) -> None:
        """Test response wrapper model."""
        response = ImageResponse(
            data=ImageData(
                id="789",
                prompt="Test",
                status=ImageStatus.IN_PROGRESS,
                progress=50,
            )
        )
        assert response.data.id == "789"
        assert response.data.progress == 50


class TestImageListResponse:
    """Tests for ImageListResponse model."""

    def test_empty_list(self) -> None:
        """Test empty list response."""
        response = ImageListResponse(data=[])
        assert len(response.data) == 0

    def test_list_with_items(self) -> None:
        """Test list response with items."""
        response = ImageListResponse(
            data=[
                ImageData(id="1", prompt="p1", status=ImageStatus.COMPLETED),
                ImageData(id="2", prompt="p2", status=ImageStatus.PENDING),
            ],
            meta={"total": 2},
        )
        assert len(response.data) == 2
        assert response.meta == {"total": 2}
