from unittest.mock import patch

from lib.api.tmdbv3api.as_obj import AsObj
from lib.domain.torrent import TorrentStream
from lib.search import (
    TITLE_LANGUAGE_ENGLISH_FIRST,
    TITLE_LANGUAGE_ENGLISH_ONLY,
    TITLE_LANGUAGE_LOCALIZED_FIRST,
    SearchVariant,
    _build_title_fallback_queries,
    _perform_search_with_title_fallback,
)


def test_search_variant_enum_values():
    if not hasattr(SearchVariant, "__members__"):
        return
    assert SearchVariant.DEFAULT.value == "default"
    assert SearchVariant.TITLE_YEAR.value == "title_year"
    assert SearchVariant.ORIGINAL_TITLE.value == "original_title"
    assert SearchVariant.ORIGINAL_TITLE_YEAR.value == "original_title_year"


def test_build_title_fallback_queries_default_variant_uses_fallback_behavior():
    details = AsObj(
        {
            "original_title": "The Intouchables",
            "translations": {
                "translations": [
                    {"iso_639_1": "en", "data": {"title": "The Intouchables"}},
                ]
            },
        }
    )

    with patch("lib.clients.tmdb.utils.utils.get_tmdb_media_details", return_value=details):
        queries = _build_title_fallback_queries(
            "Intocable",
            {"tmdb_id": "77338"},
            "movies",
            variant=SearchVariant.DEFAULT,
        )

    assert "Intocable" in queries
    assert "The Intouchables" in queries


def test_build_title_fallback_queries_title_year_appends_year():
    queries = _build_title_fallback_queries(
        "Inception",
        {"tmdb_id": "27205"},
        "movies",
        variant=SearchVariant.TITLE_YEAR,
        year=2010,
    )

    assert queries == ["Inception 2010"]


def test_build_title_fallback_queries_original_title_uses_tmdb_original():
    details = AsObj(
        {
            "original_title": "千と千尋の神隠し",
            "translations": {
                "translations": [
                    {"iso_639_1": "en", "data": {"title": "Spirited Away"}},
                ]
            },
        }
    )

    with patch("lib.clients.tmdb.utils.utils.get_tmdb_media_details", return_value=details):
        queries = _build_title_fallback_queries(
            "Spirited Away",
            {"tmdb_id": "129"},
            "movies",
            variant=SearchVariant.ORIGINAL_TITLE,
        )

    assert queries == ["千と千尋の神隠し"]


def test_build_title_fallback_queries_original_title_year_appends_year():
    details = AsObj(
        {
            "original_title": "千と千尋の神隠し",
            "translations": {
                "translations": [
                    {"iso_639_1": "en", "data": {"title": "Spirited Away"}},
                ]
            },
        }
    )

    with patch("lib.clients.tmdb.utils.utils.get_tmdb_media_details", return_value=details):
        queries = _build_title_fallback_queries(
            "Spirited Away",
            {"tmdb_id": "129"},
            "movies",
            variant=SearchVariant.ORIGINAL_TITLE_YEAR,
            year=2001,
        )

    assert queries == ["千と千尋の神隠し 2001"]


def test_build_title_fallback_queries_title_year_without_ids():
    queries = _build_title_fallback_queries(
        "Inception",
        {},
        "movies",
        variant=SearchVariant.TITLE_YEAR,
        year=2010,
    )

    assert queries == ["Inception 2010"]


def test_build_title_fallback_queries_original_title_fallbacks_to_query():
    details = AsObj(
        {
            "original_title": "",
            "translations": {
                "translations": [
                    {"iso_639_1": "en", "data": {"title": "Some Movie"}},
                ]
            },
        }
    )

    with patch("lib.clients.tmdb.utils.utils.get_tmdb_media_details", return_value=details):
        queries = _build_title_fallback_queries(
            "Some Movie",
            {"tmdb_id": "123"},
            "movies",
            variant=SearchVariant.ORIGINAL_TITLE,
        )

    assert queries == ["Some Movie"]


def test_build_title_fallback_queries_prefers_english_translation_for_movies():
    details = AsObj(
        {
            "original_title": "The Intouchables",
            "translations": {
                "translations": [
                    {"iso_639_1": "es", "data": {"title": "Intocable"}},
                    {
                        "iso_639_1": "en",
                        "data": {"title": "The Intouchables"},
                    },
                ]
            },
        }
    )

    with patch("lib.clients.tmdb.utils.utils.get_tmdb_media_details", return_value=details):
        queries = _build_title_fallback_queries(
            "Intocable",
            {"tmdb_id": "77338"},
            "movies",
            title_language_mode=TITLE_LANGUAGE_LOCALIZED_FIRST,
        )

    assert queries == ["Intocable", "The Intouchables"]


def test_build_title_fallback_queries_english_first_reorders_candidates():
    details = AsObj(
        {
            "original_title": "The Intouchables",
            "translations": {
                "translations": [
                    {"iso_639_1": "es", "data": {"title": "Intocable"}},
                    {
                        "iso_639_1": "en",
                        "data": {"title": "The Intouchables"},
                    },
                ]
            },
        }
    )

    with patch("lib.clients.tmdb.utils.utils.get_tmdb_media_details", return_value=details):
        queries = _build_title_fallback_queries(
            "Intocable",
            {"tmdb_id": "77338"},
            "movies",
            title_language_mode=TITLE_LANGUAGE_ENGLISH_FIRST,
        )

    assert queries == ["The Intouchables", "Intocable"]


def test_build_title_fallback_queries_english_first_falls_back_to_original_before_localized():
    details = AsObj(
        {
            "original_title": "Avatar: Fire and Ash",
            "translations": {
                "translations": [
                    {"iso_639_1": "es", "data": {"title": "Avatar: Fuego y ceniza"}},
                ]
            },
        }
    )

    with patch("lib.clients.tmdb.utils.utils.get_tmdb_media_details", return_value=details):
        queries = _build_title_fallback_queries(
            "Avatar: Fuego y ceniza",
            {"tmdb_id": "123456"},
            "movies",
            title_language_mode=TITLE_LANGUAGE_ENGLISH_FIRST,
        )

    assert queries == ["Avatar: Fire and Ash", "Avatar: Fuego y ceniza"]


def test_build_title_fallback_queries_english_only_skips_localized_query():
    details = AsObj(
        {
            "original_title": "The Intouchables",
            "translations": {
                "translations": [
                    {"iso_639_1": "es", "data": {"title": "Intocable"}},
                    {
                        "iso_639_1": "en",
                        "data": {"title": "The Intouchables"},
                    },
                ]
            },
        }
    )

    with patch("lib.clients.tmdb.utils.utils.get_tmdb_media_details", return_value=details):
        queries = _build_title_fallback_queries(
            "Intocable",
            {"tmdb_id": "77338"},
            "movies",
            title_language_mode=TITLE_LANGUAGE_ENGLISH_ONLY,
        )

    assert queries == ["The Intouchables"]


def test_build_title_fallback_queries_uses_original_name_when_needed_for_tv():
    details = AsObj(
        {
            "original_name": "Shingeki no Kyojin",
            "translations": {
                "translations": [
                    {"iso_639_1": "de", "data": {"name": "Attack on Titan"}},
                    {
                        "iso_639_1": "en",
                        "data": {"name": "Attack on Titan"},
                    },
                ]
            },
        }
    )

    with patch("lib.clients.tmdb.utils.utils.get_tmdb_media_details", return_value=details):
        queries = _build_title_fallback_queries("Ataque a los Titanes", {"tmdb_id": "1429"}, "tv")

    assert queries == [
        "Ataque a los Titanes",
        "Attack on Titan",
        "Shingeki no Kyojin",
    ]


def test_perform_search_with_title_fallback_retries_until_results_found():
    expected = [TorrentStream(title="The Intouchables 2011")]

    with patch(
        "lib.search._build_title_fallback_queries",
        return_value=["Intocable", "The Intouchables", "Untouchables"],
    ), patch(
        "lib.search._perform_search",
        side_effect=[[], expected],
    ) as mock_search:
        results = _perform_search_with_title_fallback(
            "Prowlarr", None, "Intocable", {"tmdb_id": "77338"}, "movies", None, None
        )

    assert results == expected
    assert mock_search.call_count == 2
    assert mock_search.call_args_list[0].args == (
        "Prowlarr",
        None,
        "Intocable",
        "movies",
        None,
        None,
    )
    assert mock_search.call_args_list[1].args == (
        "Prowlarr",
        None,
        "The Intouchables",
        "movies",
        None,
        None,
    )
