"""Unit tests for anime Pydantic models.

This module tests all anime-related models including validation,
serialization, and field constraints.
"""
import pytest
from pydantic import ValidationError

from src.server.models.anime import (
    AnimeSeriesResponse,
    EpisodeInfo,
    MissingEpisodeInfo,
    SearchRequest,
    SearchResult,
)


class TestEpisodeInfo:
    """Tests for EpisodeInfo model."""

    def test_episode_info_basic(self):
        """Test creating a basic episode info."""
        ep = EpisodeInfo(episode_number=1, title="Pilot", duration_seconds=1500)
        assert ep.episode_number == 1
        assert ep.title == "Pilot"
        assert ep.duration_seconds == 1500
        assert ep.available is True

    def test_episode_info_without_optional_fields(self):
        """Test episode info with only required fields."""
        ep = EpisodeInfo(episode_number=5)
        assert ep.episode_number == 5
        assert ep.title is None
        assert ep.duration_seconds is None
        assert ep.available is True

    def test_invalid_episode_number(self):
        """Test that episode number must be positive."""
        with pytest.raises(ValidationError):
            EpisodeInfo(episode_number=0)


class TestMissingEpisodeInfo:
    """Tests for MissingEpisodeInfo model."""

    def test_missing_episode_count(self):
        """Test count property calculation."""
        m = MissingEpisodeInfo(from_episode=5, to_episode=7)
        assert m.count == 3

    def test_single_missing_episode(self):
        """Test count for single missing episode."""
        m = MissingEpisodeInfo(from_episode=5, to_episode=5)
        assert m.count == 1


class TestAnimeSeriesResponse:
    """Tests for AnimeSeriesResponse model."""

    def test_anime_series_response_with_key(self):
        """Test creating series response with key as identifier."""
        ep = EpisodeInfo(episode_number=1, title="Ep1")
        series = AnimeSeriesResponse(
            key="attack-on-titan",
            title="Attack on Titan",
            folder="Attack on Titan (2013)",
            episodes=[ep],
        )

        assert series.key == "attack-on-titan"
        assert series.title == "Attack on Titan"
        assert series.folder == "Attack on Titan (2013)"
        assert series.episodes[0].title == "Ep1"

    def test_key_normalization(self):
        """Test that key is normalized to lowercase."""
        series = AnimeSeriesResponse(
            key="ATTACK-ON-TITAN",
            title="Attack on Titan"
        )
        assert series.key == "attack-on-titan"

    def test_key_whitespace_stripped(self):
        """Test that key whitespace is stripped."""
        series = AnimeSeriesResponse(
            key="  attack-on-titan  ",
            title="Attack on Titan"
        )
        assert series.key == "attack-on-titan"

    def test_folder_is_optional(self):
        """Test that folder is optional metadata."""
        series = AnimeSeriesResponse(
            key="my-anime",
            title="My Anime"
        )
        assert series.folder is None


class TestSearchRequest:
    """Tests for SearchRequest model."""

    def test_search_request_validation(self):
        """Test valid search request."""
        req = SearchRequest(query="naruto", limit=5)
        assert req.query == "naruto"
        assert req.limit == 5

    def test_search_request_empty_query_rejected(self):
        """Test that empty query is rejected."""
        with pytest.raises(ValidationError):
            SearchRequest(query="", limit=5)

    def test_search_request_defaults(self):
        """Test default values."""
        req = SearchRequest(query="test")
        assert req.limit == 10
        assert req.include_adult is False


class TestSearchResult:
    """Tests for SearchResult model."""

    def test_search_result_with_key(self):
        """Test search result with key as identifier."""
        res = SearchResult(
            key="naruto",
            title="Naruto",
            folder="Naruto (2002)",
            snippet="A ninja story",
            score=0.9
        )
        assert res.key == "naruto"
        assert res.title == "Naruto"
        assert res.folder == "Naruto (2002)"
        assert res.score == 0.9

    def test_key_normalization(self):
        """Test that key is normalized to lowercase."""
        res = SearchResult(key="NARUTO", title="Naruto")
        assert res.key == "naruto"

    def test_folder_is_optional(self):
        """Test that folder is optional metadata."""
        res = SearchResult(key="test", title="Test")
        assert res.folder is None

    def test_optional_fields(self):
        """Test optional fields."""
        res = SearchResult(key="s1", title="T1", snippet="snip", score=0.9)
        assert res.score == 0.9
        assert res.snippet == "snip"
