"""Tests for folder ignore patterns feature."""
import os
import tempfile
import warnings
from unittest.mock import patch

import pytest

from src.config.settings import Settings


class TestShouldIgnoreFolder:
    """Test should_ignore_folder method."""

    def test_ignore_pattern_matches_exact(self):
        """Test exact folder name match."""
        settings = Settings()
        assert settings.should_ignore_folder("The Last of Us") is True

    def test_ignore_pattern_matches_case_insensitive(self):
        """Test case-insensitive matching."""
        settings = Settings()
        assert settings.should_ignore_folder("the last of us") is True
        assert settings.should_ignore_folder("THE LAST OF US") is True

    def test_ignore_pattern_partial_match(self):
        """Test partial folder name match."""
        settings = Settings()
        assert settings.should_ignore_folder("Loki Season 2") is True
        assert settings.should_ignore_folder("Chernobyl Complete") is True

    def test_non_matching_folder_returns_false(self):
        """Test non-matching folder passes through."""
        settings = Settings()
        assert settings.should_ignore_folder("Attack on Titan") is False
        assert settings.should_ignore_folder("Naruto") is False

    def test_empty_folder_returns_false(self):
        """Test empty folder name."""
        settings = Settings()
        assert settings.should_ignore_folder("") is False

    def test_custom_patterns_via_env_var(self, monkeypatch):
        """Test custom ignore patterns via environment variable."""
        monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "MyShow|AnotherShow")
        settings = Settings()
        assert settings.should_ignore_folder("MyShow") is True
        assert settings.should_ignore_folder("AnotherShow") is True
        assert settings.should_ignore_folder("OtherShow") is False

    def test_custom_patterns_case_insensitive_via_env_var(self, monkeypatch):
        """Test custom patterns respect case-insensitivity via env var."""
        monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "myshow")
        settings = Settings()
        assert settings.should_ignore_folder("MyShow") is True
        assert settings.should_ignore_folder("MYSHOW") is True


class TestFolderIgnorePatternsProperty:
    """Test folder_ignore_patterns property."""

    def test_default_patterns_parsed(self):
        """Test default patterns are parsed correctly."""
        settings = Settings()
        patterns = settings.folder_ignore_patterns
        assert len(patterns) > 0
        assert "The Last of Us" in patterns
        assert "Loki" in patterns

    def test_empty_string_via_env_var_returns_empty_list(self, monkeypatch):
        """Test empty patterns string via env var."""
        monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "")
        settings = Settings()
        patterns = settings.folder_ignore_patterns
        assert patterns == []

    def test_single_pattern_via_env_var(self, monkeypatch):
        """Test single pattern via env var."""
        monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "TestShow")
        settings = Settings()
        patterns = settings.folder_ignore_patterns
        # Single pattern in pipe-separated string
        assert "TestShow" in patterns

    def test_pipe_separated_patterns_via_env_var(self, monkeypatch):
        """Test pipe-separated patterns via env var."""
        monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "Show1|Show2|Show3")
        settings = Settings()
        patterns = settings.folder_ignore_patterns
        assert len(patterns) == 3
        assert "Show1" in patterns
        assert "Show2" in patterns
        assert "Show3" in patterns

    def test_pattern_with_spaces_trimmed_via_env_var(self, monkeypatch):
        """Test patterns with spaces are trimmed."""
        monkeypatch.setenv("NFO_FOLDER_IGNORE_PATTERNS", "Show1 | Show2 | Show3 ")
        settings = Settings()
        patterns = settings.folder_ignore_patterns
        # All patterns should be trimmed of whitespace
        for p in patterns:
            assert p == p.strip()


class TestSerieScannerIgnorePatterns:
    """Test SerieScanner respects ignore patterns."""

    def test_scanner_skips_ignored_folders(self, tmp_path):
        """Test scanner skips folders matching ignore patterns."""
        from src.core.SerieScanner import SerieScanner
        from src.core.providers.aniworld_provider import AniworldLoader

        # Create test folders
        ignored_folder = tmp_path / "The Last of Us"
        ignored_folder.mkdir()
        (ignored_folder / "S01E01.mp4").touch()

        normal_folder = tmp_path / "Attack on Titan"
        normal_folder.mkdir()
        (normal_folder / "S01E01.mp4").touch()

        loader = AniworldLoader()
        scanner = SerieScanner(str(tmp_path), loader)

        # Get MP4 files - should only find Attack on Titan
        mp4_files = list(scanner._SerieScanner__find_mp4_files())
        folder_names = [name for name, _ in mp4_files]

        assert "Attack on Titan" in folder_names
        assert "The Last of Us" not in folder_names

    def test_scanner_normal_folders_not_ignored(self, tmp_path):
        """Test normal folders are not skipped."""
        from src.core.SerieScanner import SerieScanner
        from src.core.providers.aniworld_provider import AniworldLoader

        folder1 = tmp_path / "Attack on Titan"
        folder1.mkdir()
        (folder1 / "S01E01.mp4").touch()

        folder2 = tmp_path / "Naruto"
        folder2.mkdir()
        (folder2 / "S01E01.mp4").touch()

        loader = AniworldLoader()
        scanner = SerieScanner(str(tmp_path), loader)

        mp4_files = list(scanner._SerieScanner__find_mp4_files())
        folder_names = [name for name, _ in mp4_files]

        assert "Attack on Titan" in folder_names
        assert "Naruto" in folder_names

    def test_scanner_respects_default_ignore_patterns(self, tmp_path):
        """Test scanner respects default ignore patterns."""
        from src.core.SerieScanner import SerieScanner
        from src.core.providers.aniworld_provider import AniworldLoader

        # Create folder matching default ignore pattern (Chernobyl)
        ignored_folder = tmp_path / "Chernobyl Complete Series"
        ignored_folder.mkdir()
        (ignored_folder / "S01E01.mp4").touch()

        normal_folder = tmp_path / "Normal Anime"
        normal_folder.mkdir()
        (normal_folder / "S01E01.mp4").touch()

        loader = AniworldLoader()
        scanner = SerieScanner(str(tmp_path), loader)
        mp4_files = list(scanner._SerieScanner__find_mp4_files())
        folder_names = [name for name, _ in mp4_files]

        assert "Normal Anime" in folder_names
        assert "Chernobyl Complete Series" not in folder_names


class TestSerieListIgnorePatterns:
    """Test SerieList respects ignore patterns."""

    def test_load_series_skips_ignored_folders(self, tmp_path):
        """Test load_series skips folders matching ignore patterns."""
        from src.core.entities.SerieList import SerieList
        from src.core.entities.series import Serie

        # Create ignored folder with data file
        ignored_folder = tmp_path / "The Last of Us"
        ignored_folder.mkdir()
        ignored_data = ignored_folder / "data"
        
        ignored_serie = Serie(
            key="the-last-of-us",
            name="The Last of Us",
            site="https://aniworld.to/anime/stream/the-last-of-us",
            folder="The Last of Us",
            episodeDict={1: [1, 2, 3]}
        )
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", DeprecationWarning)
            ignored_serie.save_to_file(str(ignored_data))

        # Create normal folder with data file
        normal_folder = tmp_path / "Attack on Titan"
        normal_folder.mkdir()
        normal_data = normal_folder / "data"
        
        normal_serie = Serie(
            key="attack-on-titan",
            name="Attack on Titan",
            site="https://aniworld.to/anime/stream/attack-on-titan",
            folder="Attack on Titan",
            episodeDict={1: [1, 2]}
        )
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", DeprecationWarning)
            normal_serie.save_to_file(str(normal_data))

        # Load series
        serie_list = SerieList(str(tmp_path))
        
        # Verify ignored folder was skipped
        assert serie_list.contains("attack-on-titan") is True
        assert serie_list.contains("the-last-of-us") is False