"""Unit tests for minimal NFO creation when TMDB fails.

Tests the fallback behavior when TMDB lookup fails and we need to create
a minimal NFO file just to track the series.
"""
from pathlib import Path
from unittest.mock import AsyncMock, patch

import pytest

from src.core.services.nfo_service import NFOService


@pytest.fixture
def nfo_service(tmp_path):
    """Create NFO service with test directory.
    
    Note: anime_directory is set to tmp_path directly (not tmp_path / "anime")
    because tmp_path already represents the test anime directory.
    """
    service = NFOService(
        tmdb_api_key="test_api_key",
        anime_directory=str(tmp_path),
        image_size="w500",
        auto_create=True
    )
    return service


class TestCreateMinimalNFO:
    """Test minimal NFO creation."""

    @pytest.mark.asyncio
    async def test_create_minimal_nfo_basic(self, nfo_service, tmp_path):
        """Test creating minimal NFO with just title."""
        # Setup - anime_directory is already tmp_path
        serie_folder = "Test Series"
        
        # Create minimal NFO
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="Test Series",
            serie_folder=serie_folder
        )
        
        # Verify
        assert nfo_path.exists()
        assert nfo_path.name == "tvshow.nfo"
        
        content = nfo_path.read_text(encoding="utf-8")
        assert "<title>Test Series</title>" in content
        assert "No metadata available" in content

    @pytest.mark.asyncio
    async def test_create_minimal_nfo_with_year(self, nfo_service, tmp_path):
        """Test creating minimal NFO with year."""
        # Setup - anime_directory is already tmp_path
        serie_folder = "Test Series (2024)"
        
        # Create minimal NFO with explicit year
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="Test Series",
            serie_folder=serie_folder,
            year=2024
        )
        
        # Verify
        assert nfo_path.exists()
        content = nfo_path.read_text(encoding="utf-8")
        assert "<title>Test Series</title>" in content
        assert "<year>2024</year>" in content

    @pytest.mark.asyncio
    async def test_create_minimal_nfo_extracts_year_from_name(self, nfo_service, tmp_path):
        """Test that year is extracted from series name format (YYYY)."""
        # Setup - anime_directory is already tmp_path
        serie_folder = "Test Series (2024)"
        
        # Create with name that has year
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="Test Series (2024)",
            serie_folder=serie_folder
        )
        
        # Verify year was extracted
        assert nfo_path.exists()
        content = nfo_path.read_text(encoding="utf-8")
        assert "<title>Test Series</title>" in content
        assert "<year>2024</year>" in content

    @pytest.mark.asyncio
    async def test_create_minimal_nfo_creates_folder_if_missing(self, nfo_service, tmp_path):
        """Test that folder is created if it doesn't exist."""
        # Setup - anime_directory is tmp_path itself
        serie_folder = "New Series"
        
        # Folder should not exist yet (under anime_directory which is tmp_path)
        folder_path = tmp_path / serie_folder
        assert not folder_path.exists()
        
        # Create minimal NFO
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="New Series",
            serie_folder=serie_folder
        )
        
        # Verify folder and file were created
        assert folder_path.exists()
        assert nfo_path.exists()

    @pytest.mark.asyncio
    async def test_create_minimal_nfo_xml_is_valid(self, nfo_service, tmp_path):
        """Test that generated XML is valid."""
        # Create minimal NFO (anime_directory is already tmp_path)
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="Test Anime",
            serie_folder="Test Anime",
            year=2020
        )
        
        # Verify XML is valid
        from lxml import etree
        content = nfo_path.read_text(encoding="utf-8")
        
        # Should parse without errors
        tree = etree.fromstring(content.encode("utf-8"))
        assert tree is not None
        assert tree.tag == "tvshow"
        
        # Check title element
        title = tree.find("title")
        assert title is not None
        assert title.text == "Test Anime"

    @pytest.mark.asyncio
    async def test_create_minimal_nfo_no_tmdb_id(self, nfo_service, tmp_path):
        """Test that minimal NFO has no TMDB ID."""
        # Create minimal NFO (anime_directory is already tmp_path)
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="Unknown Series",
            serie_folder="Unknown Series",
            year=1999
        )
        
        # Verify no TMDB ID
        content = nfo_path.read_text(encoding="utf-8")
        assert "<tmdbid>" not in content
        assert "uniqueid" not in content

    @pytest.mark.asyncio
    async def test_create_minimal_nfo_has_plot_explanation(self, nfo_service, tmp_path):
        """Test that minimal NFO contains explanation in plot."""
        # Create minimal NFO (anime_directory is already tmp_path)
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="Mysterious Anime",
            serie_folder="Mysterious Anime"
        )
        
        # Verify plot explains why metadata is missing
        content = nfo_path.read_text(encoding="utf-8")
        assert "TMDB lookup failed" in content
        assert "Mysterious Anime" in content


class TestCreateMinimalNFOIntegration:
    """Integration tests for minimal NFO with TMDB failure scenarios."""

    @pytest.mark.asyncio
    async def test_fallback_on_tmdb_search_failure(self, nfo_service, tmp_path):
        """Test that minimal NFO is created when TMDB search fails."""
        # Mock TMDB client to raise error
        nfo_service.tmdb_client.search_tv_show = AsyncMock(
            side_effect=Exception("TMDB API Error")
        )
        
        # Try to create full NFO (should fail and fallback to minimal)
        # We test the fallback method directly
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="Failed Series",
            serie_folder="Failed Series",
            year=2021
        )
        
        # Verify
        assert nfo_path.exists()
        content = nfo_path.read_text(encoding="utf-8")
        assert "<title>Failed Series</title>" in content
        assert "<year>2021</year>" in content

    @pytest.mark.asyncio
    async def test_minimal_nfo_allows_series_tracking(self, nfo_service, tmp_path):
        """Test that minimal NFO allows series to be tracked."""
        # anime_directory is already tmp_path
        serie_folder = "Untracked Series"
        
        # Create minimal NFO
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="Untracked Series",
            serie_folder=serie_folder,
            year=2018
        )
        
        # Verify NFO exists (series can be tracked)
        assert nfo_service.has_nfo(serie_folder) is True
        
        # Verify minimal content
        content = nfo_path.read_text(encoding="utf-8")
        assert "<title>Untracked Series</title>" in content


class TestMinimalNFOContent:
    """Test content of minimal NFO files."""

    @pytest.mark.asyncio
    async def test_minimal_nfo_contains_required_elements(self, nfo_service, tmp_path):
        """Test that minimal NFO has title and plot."""
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="Minimal Test",
            serie_folder="Minimal Test"
        )
        
        content = nfo_path.read_text(encoding="utf-8")
        
        # Must have title
        assert "<title>Minimal Test</title>" in content
        # Must have plot explaining situation
        assert "plot" in content.lower()
        assert "No metadata available" in content

    @pytest.mark.asyncio
    async def test_minimal_nfo_xml_declaration(self, nfo_service, tmp_path):
        """Test that NFO has proper XML declaration."""
        nfo_path = await nfo_service.create_minimal_nfo(
            serie_name="XML Test",
            serie_folder="XML Test"
        )
        
        content = nfo_path.read_text(encoding="utf-8")
        
        # Should have XML declaration
        assert content.startswith('<?xml version="1.0" encoding="UTF-8"')