"""
Unit tests for Pydantic models
"""
import pytest
from datetime import datetime
from pydantic import ValidationError

from app.models import (
    DownloadTask,
    DownloadStatus,
    DownloadRequest,
    HostType,
    AnimeMetadata,
    AnimeSearchResult
)


class TestDownloadStatus:
    """Tests for DownloadStatus enum"""

    def test_status_values(self):
        """Test that all status values are correct"""
        assert DownloadStatus.PENDING == "pending"
        assert DownloadStatus.DOWNLOADING == "downloading"
        assert DownloadStatus.PAUSED == "paused"
        assert DownloadStatus.COMPLETED == "completed"
        assert DownloadStatus.FAILED == "failed"
        assert DownloadStatus.CANCELLED == "cancelled"

    def test_status_comparison(self):
        """Test status comparison"""
        status1 = DownloadStatus.PENDING
        status2 = DownloadStatus.DOWNLOADING
        assert status1 != status2
        assert status1 == "pending"


class TestHostType:
    """Tests for HostType enum"""

    def test_host_values(self):
        """Test that all host type values are correct"""
        assert HostType.RAPIDFILE == "rapidfile"
        assert HostType.UNFICHIER == "1fichier"
        assert HostType.DOODSTREAM == "doodstream"
        assert HostType.OTHER == "other"


class TestDownloadTask:
    """Tests for DownloadTask model"""

    def test_create_download_task_valid(self, sample_download_task):
        """Test creating a valid download task"""
        task = sample_download_task
        assert task.id == "test-task-123"
        assert task.url == "https://example.com/file.mp4"
        assert task.filename == "test_video.mp4"
        assert task.host == HostType.OTHER
        assert task.status == DownloadStatus.PENDING
        assert task.progress == 0.0
        assert task.downloaded_bytes == 0
        assert task.total_bytes is None
        assert task.speed == 0.0

    def test_download_task_with_optional_fields(self):
        """Test download task with all optional fields"""
        now = datetime.now()
        task = DownloadTask(
            id="task-456",
            url="https://example.com/file2.mp4",
            filename="file2.mp4",
            host=HostType.DOODSTREAM,
            status=DownloadStatus.DOWNLOADING,
            progress=50.0,
            downloaded_bytes=5000000,
            total_bytes=10000000,
            speed=1000000.0,
            error="Test error",
            created_at=now,
            started_at=now,
            completed_at=None,
            file_path="/downloads/file2.mp4"
        )
        assert task.progress == 50.0
        assert task.downloaded_bytes == 5000000
        assert task.total_bytes == 10000000
        assert task.speed == 1000000.0
        assert task.error == "Test error"
        assert task.started_at is not None
        assert task.completed_at is None
        assert task.file_path == "/downloads/file2.mp4"

    def test_download_task_default_values(self):
        """Test download task with default values"""
        task = DownloadTask(
            id="task-default",
            url="https://example.com/file.mp4",
            filename="file.mp4",
            host=HostType.OTHER,
            status=DownloadStatus.PENDING,
            created_at=datetime.now()
        )
        assert task.progress == 0.0
        assert task.downloaded_bytes == 0
        assert task.speed == 0.0
        assert task.total_bytes is None
        assert task.error is None
        assert task.started_at is None
        assert task.completed_at is None
        assert task.file_path is None

    def test_download_task_invalid_url(self):
        """Test that task accepts any URL string (Pydantic v2 doesn't validate URL by default)"""
        # Pydantic v2 doesn't validate URL format by default unless explicitly configured
        # This test documents the current behavior
        task = DownloadTask(
            id="task-invalid",
            url="not-a-valid-url",
            filename="file.mp4",
            host=HostType.OTHER,
            status=DownloadStatus.PENDING,
            created_at=datetime.now()
        )
        assert task.url == "not-a-valid-url"

    def test_download_task_negative_progress(self):
        """Test that negative progress is accepted (validation not configured)"""
        # Pydantic v2 doesn't validate ranges by default
        task = DownloadTask(
            id="task-negative",
            url="https://example.com/file.mp4",
            filename="file.mp4",
            host=HostType.OTHER,
            status=DownloadStatus.PENDING,
            progress=-10.0,  # Accepted but not ideal
            created_at=datetime.now()
        )
        assert task.progress == -10.0

    def test_download_task_progress_over_100(self):
        """Test that progress over 100 is accepted (validation not configured)"""
        # Pydantic v2 doesn't validate ranges by default
        task = DownloadTask(
            id="task-over100",
            url="https://example.com/file.mp4",
            filename="file.mp4",
            host=HostType.OTHER,
            status=DownloadStatus.PENDING,
            progress=150.0,  # Accepted but not ideal
            created_at=datetime.now()
        )
        assert task.progress == 150.0


class TestDownloadRequest:
    """Tests for DownloadRequest model"""

    def test_create_request_with_filename(self, sample_download_request):
        """Test creating download request with filename"""
        request = sample_download_request
        assert request.url == "https://example.com/file.mp4"
        assert request.filename == "test_video.mp4"

    def test_create_request_without_filename(self):
        """Test creating download request without filename"""
        request = DownloadRequest(url="https://example.com/file.mp4")
        assert request.url == "https://example.com/file.mp4"
        assert request.filename is None

    def test_request_invalid_url(self):
        """Test that request accepts any URL string"""
        # Pydantic v2 doesn't validate URL format by default
        request = DownloadRequest(url="not-a-url")
        assert request.url == "not-a-url"

    def test_request_empty_url(self):
        """Test that empty URL is accepted"""
        # Pydantic v2 doesn't validate empty strings by default
        request = DownloadRequest(url="")
        assert request.url == ""


class TestAnimeMetadata:
    """Tests for AnimeMetadata model"""

    def test_create_metadata_all_fields(self):
        """Test creating metadata with all fields"""
        metadata = AnimeMetadata(
            synopsis="Test anime about adventure",
            genres=["Action", "Adventure", "Fantasy"],
            rating="8.5/10",
            release_year=2023,
            studio="Test Studio",
            poster_image="https://example.com/poster.jpg",
            banner_image="https://example.com/banner.jpg",
            total_episodes=12,
            status="Completed",
            alternative_titles=["Test Anime 1", "Test Anime 2"]
        )
        assert metadata.synopsis == "Test anime about adventure"
        assert len(metadata.genres) == 3
        assert metadata.rating == "8.5/10"
        assert metadata.release_year == 2023
        assert metadata.studio == "Test Studio"
        assert metadata.poster_image is not None
        assert metadata.banner_image is not None
        assert metadata.total_episodes == 12
        assert metadata.status == "Completed"
        assert len(metadata.alternative_titles) == 2

    def test_create_metadata_minimal(self):
        """Test creating metadata with minimal fields"""
        metadata = AnimeMetadata()
        assert metadata.synopsis is None
        assert metadata.genres == []
        assert metadata.rating is None
        assert metadata.release_year is None
        assert metadata.studio is None
        assert metadata.poster_image is None
        assert metadata.banner_image is None
        assert metadata.total_episodes is None
        assert metadata.status is None
        assert metadata.alternative_titles == []

    def test_metadata_with_some_fields(self):
        """Test creating metadata with only some fields"""
        metadata = AnimeMetadata(
            genres=["Action"],
            rating="PG-13",
            release_year=2020
        )
        assert len(metadata.genres) == 1
        assert metadata.genres == ["Action"]
        assert metadata.rating == "PG-13"
        assert metadata.release_year == 2020
        assert metadata.synopsis is None
        assert metadata.studio is None

    def test_metadata_empty_genres_list(self):
        """Test metadata with empty genres list"""
        metadata = AnimeMetadata(genres=[])
        assert metadata.genres == []

    def test_metadata_negative_year(self):
        """Test that negative year is handled"""
        # Pydantic doesn't validate range by default
        metadata = AnimeMetadata(release_year=-2023)
        assert metadata.release_year == -2023

    def test_metadata_zero_episodes(self):
        """Test metadata with zero episodes"""
        metadata = AnimeMetadata(total_episodes=0)
        assert metadata.total_episodes == 0


class TestAnimeSearchResult:
    """Tests for AnimeSearchResult model"""

    def test_create_search_result_full(self):
        """Test creating search result with all fields"""
        metadata = AnimeMetadata(
            synopsis="Test",
            genres=["Action"],
            rating="8.0/10"
        )
        result = AnimeSearchResult(
            title="Test Anime",
            url="https://example.com/anime",
            cover_image="https://example.com/cover.jpg",
            type="search_result",
            metadata=metadata
        )
        assert result.title == "Test Anime"
        assert result.url == "https://example.com/anime"
        assert result.cover_image == "https://example.com/cover.jpg"
        assert result.type == "search_result"
        assert result.metadata is not None
        assert result.metadata.synopsis == "Test"

    def test_create_search_result_minimal(self):
        """Test creating minimal search result"""
        result = AnimeSearchResult(
            title="Minimal Anime",
            url="https://example.com/minimal",
            type="direct"
        )
        assert result.title == "Minimal Anime"
        assert result.url == "https://example.com/minimal"
        assert result.type == "direct"
        assert result.cover_image is None
        assert result.metadata is None

    def test_search_result_invalid_type(self):
        """Test that any type string is accepted"""
        # Pydantic v2 doesn't validate literal values by default
        result = AnimeSearchResult(
            title="Test",
            url="https://example.com",
            type="invalid_type"  # Accepted
        )
        assert result.type == "invalid_type"

    def test_search_result_empty_title(self):
        """Test that empty title is accepted"""
        # Pydantic v2 doesn't validate empty strings by default
        result = AnimeSearchResult(
            title="",
            url="https://example.com",
            type="search_result"
        )
        assert result.title == ""

    def test_search_result_invalid_url(self):
        """Test that any URL string is accepted"""
        # Pydantic v2 doesn't validate URL format by default
        result = AnimeSearchResult(
            title="Test",
            url="not-a-url",
            type="search_result"
        )
        assert result.url == "not-a-url"
