"""Unit tests for media file utilities.

Tests media file checking, path resolution, video file counting,
and media file existence validation.
"""

from pathlib import Path

import pytest

from src.server.utils.media import (
    FANART_FILENAME,
    LOGO_FILENAME,
    NFO_FILENAME,
    POSTER_FILENAME,
    VIDEO_EXTENSIONS,
    check_media_files,
    count_video_files,
    get_media_file_paths,
    has_all_images,
    has_video_files,
)


class TestCheckMediaFiles:
    """Tests for check_media_files function."""

    def test_all_files_exist(self, tmp_path: Path):
        """Returns True for all file types when they exist."""
        (tmp_path / POSTER_FILENAME).touch()
        (tmp_path / LOGO_FILENAME).touch()
        (tmp_path / FANART_FILENAME).touch()
        (tmp_path / NFO_FILENAME).touch()
        result = check_media_files(tmp_path)
        assert result == {
            "poster": True, "logo": True,
            "fanart": True, "nfo": True,
        }

    def test_no_files_exist(self, tmp_path: Path):
        """Returns False for all when no media files exist."""
        result = check_media_files(tmp_path)
        assert all(v is False for v in result.values())

    def test_partial_files(self, tmp_path: Path):
        """Returns mixed results when some files exist."""
        (tmp_path / POSTER_FILENAME).touch()
        result = check_media_files(tmp_path)
        assert result["poster"] is True
        assert result["logo"] is False

    def test_accepts_string_path(self, tmp_path: Path):
        """Works with string path arguments."""
        (tmp_path / POSTER_FILENAME).touch()
        result = check_media_files(str(tmp_path))
        assert result["poster"] is True

    def test_selective_checks(self, tmp_path: Path):
        """Only checks requested file types."""
        result = check_media_files(
            tmp_path, check_poster=True, check_logo=False,
            check_fanart=False, check_nfo=False,
        )
        assert "poster" in result
        assert "logo" not in result
        assert "fanart" not in result
        assert "nfo" not in result


class TestGetMediaFilePaths:
    """Tests for get_media_file_paths function."""

    def test_returns_paths_for_existing_files(self, tmp_path: Path):
        """Returns Path objects for files that exist."""
        (tmp_path / POSTER_FILENAME).touch()
        result = get_media_file_paths(tmp_path)
        assert result["poster"] == tmp_path / POSTER_FILENAME

    def test_returns_none_for_missing_files(self, tmp_path: Path):
        """Returns None for files that don't exist."""
        result = get_media_file_paths(tmp_path)
        assert result["poster"] is None
        assert result["logo"] is None

    def test_selective_includes(self, tmp_path: Path):
        """Only includes requested file types."""
        result = get_media_file_paths(
            tmp_path, include_poster=True, include_logo=False,
            include_fanart=False, include_nfo=False,
        )
        assert "poster" in result
        assert "logo" not in result

    def test_accepts_string_path(self, tmp_path: Path):
        """Works with string path arguments."""
        (tmp_path / NFO_FILENAME).touch()
        result = get_media_file_paths(str(tmp_path))
        assert result["nfo"] is not None


class TestHasAllImages:
    """Tests for has_all_images function."""

    def test_true_when_all_images_present(self, tmp_path: Path):
        """Returns True when poster, logo, and fanart all exist."""
        (tmp_path / POSTER_FILENAME).touch()
        (tmp_path / LOGO_FILENAME).touch()
        (tmp_path / FANART_FILENAME).touch()
        assert has_all_images(tmp_path) is True

    def test_false_when_missing_one(self, tmp_path: Path):
        """Returns False when any image is missing."""
        (tmp_path / POSTER_FILENAME).touch()
        (tmp_path / LOGO_FILENAME).touch()
        # fanart missing
        assert has_all_images(tmp_path) is False

    def test_false_when_no_images(self, tmp_path: Path):
        """Returns False when no images exist."""
        assert has_all_images(tmp_path) is False

    def test_nfo_not_required(self, tmp_path: Path):
        """NFO file presence doesn't affect image check."""
        (tmp_path / POSTER_FILENAME).touch()
        (tmp_path / LOGO_FILENAME).touch()
        (tmp_path / FANART_FILENAME).touch()
        # NFO is not an image - shouldn't matter
        assert has_all_images(tmp_path) is True

    def test_accepts_string_path(self, tmp_path: Path):
        """Works with string path arguments."""
        assert has_all_images(str(tmp_path)) is False


class TestCountVideoFiles:
    """Tests for count_video_files function."""

    def test_counts_mp4_files(self, tmp_path: Path):
        """Counts .mp4 video files."""
        (tmp_path / "ep01.mp4").touch()
        (tmp_path / "ep02.mp4").touch()
        assert count_video_files(tmp_path) == 2

    def test_counts_multiple_extensions(self, tmp_path: Path):
        """Counts video files with various extensions."""
        (tmp_path / "ep01.mp4").touch()
        (tmp_path / "ep02.mkv").touch()
        (tmp_path / "ep03.avi").touch()
        assert count_video_files(tmp_path) == 3

    def test_ignores_non_video_files(self, tmp_path: Path):
        """Non-video files are not counted."""
        (tmp_path / "ep01.mp4").touch()
        (tmp_path / "poster.jpg").touch()
        (tmp_path / "readme.txt").touch()
        assert count_video_files(tmp_path) == 1

    def test_recursive_counts_subdirectories(self, tmp_path: Path):
        """Recursive mode counts videos in subdirectories."""
        s1 = tmp_path / "Season 1"
        s1.mkdir()
        (s1 / "ep01.mp4").touch()
        (s1 / "ep02.mp4").touch()
        s2 = tmp_path / "Season 2"
        s2.mkdir()
        (s2 / "ep01.mkv").touch()
        assert count_video_files(tmp_path, recursive=True) == 3

    def test_non_recursive_skips_subdirectories(self, tmp_path: Path):
        """Non-recursive mode only counts root-level files."""
        (tmp_path / "ep01.mp4").touch()
        sub = tmp_path / "Season 1"
        sub.mkdir()
        (sub / "ep02.mp4").touch()
        assert count_video_files(tmp_path, recursive=False) == 1

    def test_nonexistent_folder_returns_zero(self):
        """Returns 0 for nonexistent folder."""
        assert count_video_files("/nonexistent/path") == 0

    def test_empty_folder_returns_zero(self, tmp_path: Path):
        """Returns 0 for empty folder."""
        assert count_video_files(tmp_path) == 0

    def test_case_insensitive_extensions(self, tmp_path: Path):
        """Video extensions are matched case-insensitively."""
        (tmp_path / "ep01.MP4").touch()
        (tmp_path / "ep02.Mkv").touch()
        assert count_video_files(tmp_path) == 2


class TestHasVideoFiles:
    """Tests for has_video_files function."""

    def test_true_when_videos_exist(self, tmp_path: Path):
        """Returns True when video files are present."""
        (tmp_path / "ep01.mp4").touch()
        assert has_video_files(tmp_path) is True

    def test_false_when_no_videos(self, tmp_path: Path):
        """Returns False when no video files exist."""
        (tmp_path / "readme.txt").touch()
        assert has_video_files(tmp_path) is False

    def test_false_for_nonexistent_folder(self):
        """Returns False for nonexistent folder."""
        assert has_video_files("/nonexistent/path") is False

    def test_finds_videos_in_subdirectories(self, tmp_path: Path):
        """Detects videos in nested subdirectories."""
        sub = tmp_path / "Season 1"
        sub.mkdir()
        (sub / "ep01.mkv").touch()
        assert has_video_files(tmp_path) is True

    def test_all_supported_extensions(self, tmp_path: Path):
        """All supported video extensions are recognized."""
        for ext in VIDEO_EXTENSIONS:
            (tmp_path / f"test{ext}").touch()
        assert has_video_files(tmp_path) is True


class TestConstants:
    """Tests for module constants."""

    def test_standard_filenames(self):
        """Standard media filenames match Kodi/Plex conventions."""
        assert POSTER_FILENAME == "poster.jpg"
        assert LOGO_FILENAME == "logo.png"
        assert FANART_FILENAME == "fanart.jpg"
        assert NFO_FILENAME == "tvshow.nfo"

    def test_video_extensions_includes_common_formats(self):
        """VIDEO_EXTENSIONS includes all common video formats."""
        for ext in [".mp4", ".mkv", ".avi", ".webm"]:
            assert ext in VIDEO_EXTENSIONS
