from unittest.mock import patch

from lib.api.tmdbv3api.as_obj import AsObj
from lib.clients.tmdb.trailers import (
    _normalize_media_type,
    choose_tmdb_trailer,
    resolve_tmdb_trailer,
)


def test_normalize_media_type_supports_movie_and_tv_variants():
    assert _normalize_media_type("movie") == "movie"
    assert _normalize_media_type("movies") == "movie"
    assert _normalize_media_type("tv") == "tv"
    assert _normalize_media_type("shows") == "tv"


def test_normalize_media_type_returns_none_for_unsupported_values():
    assert _normalize_media_type(None) is None
    assert _normalize_media_type("documentary") is None


def test_choose_tmdb_trailer_prefers_trailer_over_teaser_then_official_flag():
    videos = [
        {
            "site": "YouTube",
            "type": "Teaser",
            "official": True,
            "key": "teaser12345A",
        },
        {
            "site": "YouTube",
            "type": "Trailer",
            "official": False,
            "key": "trailer1234",
        },
        {
            "site": "YouTube",
            "type": "Trailer",
            "official": True,
            "key": "official1234",
        },
    ]

    assert choose_tmdb_trailer(videos) == {
        "yt_id": "official1234",
        "youtube_url": "https://www.youtube.com/watch?v=official1234",
    }


def test_choose_tmdb_trailer_ignores_non_youtube_and_unrelated_types():
    videos = [
        {"site": "Vimeo", "type": "Trailer", "official": True, "key": "vimeo123456"},
        {
            "site": "YouTube",
            "type": "Behind the Scenes",
            "official": True,
            "key": "bts12345678",
        },
    ]

    assert choose_tmdb_trailer(videos) is None


def test_choose_tmdb_trailer_accepts_clip_as_lower_priority_fallback():
    videos = [
        {"site": "YouTube", "type": "Clip", "official": True, "key": "clip1234567"},
        {"site": "YouTube", "type": "Teaser", "official": False, "key": "teaser12345"},
    ]

    assert choose_tmdb_trailer(videos) == {
        "yt_id": "teaser12345",
        "youtube_url": "https://www.youtube.com/watch?v=teaser12345",
    }


def test_choose_tmdb_trailer_uses_clip_when_no_trailer_or_teaser_exists():
    videos = [
        {"site": "YouTube", "type": "Clip", "official": True, "key": "clip1234567"},
    ]

    assert choose_tmdb_trailer(videos) == {
        "yt_id": "clip1234567",
        "youtube_url": "https://www.youtube.com/watch?v=clip1234567",
    }


def test_resolve_tmdb_trailer_uses_movie_wrapper(monkeypatch):
    class FakeMovie:
        def videos(self, tmdb_id, page=1):
            assert tmdb_id == 550
            assert page == 1
            return [
                {
                    "site": "YouTube",
                    "type": "Trailer",
                    "official": True,
                    "key": "movie123456",
                }
            ]

    monkeypatch.setattr("lib.clients.tmdb.trailers.Movie", FakeMovie)

    assert resolve_tmdb_trailer(550, "movies") == {
        "yt_id": "movie123456",
        "youtube_url": "https://www.youtube.com/watch?v=movie123456",
    }


def test_resolve_tmdb_trailer_uses_tv_wrapper(monkeypatch):
    class FakeTV:
        def videos(self, tmdb_id, include_video_language=None, page=1):
            assert tmdb_id == 1399
            assert include_video_language is None
            assert page == 1
            return [
                {
                    "site": "YouTube",
                    "type": "Teaser",
                    "official": False,
                    "key": "tv123456789",
                }
            ]

    monkeypatch.setattr("lib.clients.tmdb.trailers.TV", FakeTV)

    assert resolve_tmdb_trailer(1399, "tv") == {
        "yt_id": "tv123456789",
        "youtube_url": "https://www.youtube.com/watch?v=tv123456789",
    }


def test_resolve_tmdb_trailer_handles_tv_wrapper_results_dict(monkeypatch):
    class FakeTV:
        def videos(self, tmdb_id, include_video_language=None, page=1):
            assert tmdb_id == 1416
            return {
                "id": tmdb_id,
                "results": [
                    {
                        "site": "YouTube",
                        "type": "Trailer",
                        "official": True,
                        "key": "tvresults01",
                    }
                ],
            }

    monkeypatch.setattr("lib.clients.tmdb.trailers.TV", FakeTV)

    assert resolve_tmdb_trailer(1416, "tv") == {
        "yt_id": "tvresults01",
        "youtube_url": "https://www.youtube.com/watch?v=tvresults01",
    }


def test_resolve_tmdb_trailer_handles_tv_wrapper_asobj_with_results(monkeypatch):
    class FakeTV:
        def videos(self, tmdb_id, include_video_language=None, page=1):
            return AsObj(
                {
                    "id": tmdb_id,
                    "results": [
                        {
                            "site": "YouTube",
                            "type": "Trailer",
                            "official": True,
                            "key": "tvasobj001",
                        }
                    ],
                }
            )

    monkeypatch.setattr("lib.clients.tmdb.trailers.TV", FakeTV)

    assert resolve_tmdb_trailer(1622, "tv") == {
        "yt_id": "tvasobj001",
        "youtube_url": "https://www.youtube.com/watch?v=tvasobj001",
    }


def test_resolve_tmdb_trailer_returns_none_for_invalid_media_type():
    assert resolve_tmdb_trailer(1, "person") is None


def test_resolve_tmdb_trailer_logs_when_no_candidate_found(monkeypatch):
    class FakeMovie:
        def videos(self, tmdb_id, page=1):
            return []

    monkeypatch.setattr("lib.clients.tmdb.trailers.Movie", FakeMovie)

    with patch("lib.clients.tmdb.trailers.kodilog") as log_mock:
        assert resolve_tmdb_trailer(550, "movie") is None

    log_mock.assert_called()


def test_resolve_tmdb_trailer_retries_tv_lookup_with_language_fallback(monkeypatch):
    calls = []

    class FakeTV:
        def __init__(self):
            self.language = None

        def videos(self, tmdb_id, include_video_language=None, page=1):
            calls.append((self.language, include_video_language))
            if len(calls) == 1:
                return []
            return [
                {
                    "site": "YouTube",
                    "type": "Trailer",
                    "official": True,
                    "key": "fallbacktv01",
                }
            ]

    monkeypatch.setattr("lib.clients.tmdb.trailers.TV", FakeTV)
    monkeypatch.setenv("TMDB_LANGUAGE", "es-ES")

    assert resolve_tmdb_trailer(4604, "tv") == {
        "yt_id": "fallbacktv01",
        "youtube_url": "https://www.youtube.com/watch?v=fallbacktv01",
    }
    assert calls == [
        ("es-ES", "es-ES,null"),
        ("en-US", "en-US,null"),
    ]


def test_resolve_tmdb_trailer_retries_movie_lookup_with_language_fallback(monkeypatch):
    calls = []

    class FakeMovie:
        def __init__(self):
            self.language = None

        def videos(self, tmdb_id, page=1):
            calls.append(self.language)
            if len(calls) == 1:
                return []
            return [
                {
                    "site": "YouTube",
                    "type": "Clip",
                    "official": False,
                    "key": "fallbackmv1",
                }
            ]

    monkeypatch.setattr("lib.clients.tmdb.trailers.Movie", FakeMovie)
    monkeypatch.setenv("TMDB_LANGUAGE", "fr-FR")

    assert resolve_tmdb_trailer(550, "movie") == {
        "yt_id": "fallbackmv1",
        "youtube_url": "https://www.youtube.com/watch?v=fallbackmv1",
    }
    assert calls == ["fr-FR", "en-US"]
