import os
from typing import Iterable, Optional

from lib.api.tmdbv3api.objs.movie import Movie
from lib.api.tmdbv3api.objs.tv import TV
from lib.utils.kodi.utils import kodilog

YOUTUBE_WATCH_URL = "https://www.youtube.com/watch?v={}"


def _normalize_media_type(media_type: Optional[str]) -> Optional[str]:
    if not media_type:
        return None

    normalized = str(media_type).strip().lower()
    if normalized in ("movie", "movies"):
        return "movie"
    if normalized in ("tv", "show", "shows", "series"):
        return "tv"
    return None


def choose_tmdb_trailer(videos: Optional[Iterable[dict]]) -> Optional[dict]:
    candidates = []
    for index, video in enumerate(videos or []):
        if (video.get("site") or "") != "YouTube":
            continue

        trailer_type = (video.get("type") or "").strip().lower()
        if trailer_type == "trailer":
            type_rank = 0
        elif trailer_type == "teaser":
            type_rank = 1
        elif trailer_type == "clip":
            type_rank = 2
        else:
            continue

        yt_id = video.get("key")
        if not yt_id:
            continue

        candidates.append(
            (
                type_rank,
                0 if bool(video.get("official")) else 1,
                index,
                yt_id,
            )
        )

    if not candidates:
        return None

    _, _, _, yt_id = min(candidates)
    return {
        "yt_id": yt_id,
        "youtube_url": YOUTUBE_WATCH_URL.format(yt_id),
    }


def _normalize_videos(videos):
    if videos is None:
        return []
    if isinstance(videos, dict):
        return videos.get("results") or []

    results = getattr(videos, "results", None)
    if results is not None:
        return list(results)

    return list(videos)


def _tmdb_language_attempts():
    current = os.environ.get("TMDB_LANGUAGE") or "en-US"
    attempts = []

    def add(language, include_video_language=None):
        candidate = (language, include_video_language)
        if candidate not in attempts:
            attempts.append(candidate)

    add(current, f"{current},null")
    add("en-US", "en-US,null")
    add(current, None)
    add("en-US", None)
    return attempts


def resolve_tmdb_trailer(tmdb_id, media_type: Optional[str]) -> Optional[dict]:
    normalized_media_type = _normalize_media_type(media_type)
    if not tmdb_id or not normalized_media_type:
        kodilog(
            f"Trailer/TMDB: skipped lookup tmdb_id={tmdb_id!r} media_type={media_type!r} normalized={normalized_media_type!r}"
        )
        return None

    trailer = None
    last_error = None

    for language, include_video_language in _tmdb_language_attempts():
        try:
            if normalized_media_type == "movie":
                client = Movie()
                client.language = language
                videos = client.videos(tmdb_id, page=1)
            else:
                client = TV()
                client.language = language
                videos = client.videos(
                    tmdb_id,
                    include_video_language=include_video_language,
                    page=1,
                )
        except Exception as exc:
            last_error = exc
            continue

        videos = _normalize_videos(videos)
        trailer = choose_tmdb_trailer(videos)
        if trailer:
            break

    if last_error and not trailer:
        kodilog(
            f"Trailer/TMDB: lookup failed tmdb_id={tmdb_id!r} media_type={normalized_media_type!r} error={last_error}"
        )

    if not trailer:
        kodilog(
            f"Trailer/TMDB: no youtube trailer found tmdb_id={tmdb_id!r} media_type={normalized_media_type!r}"
        )
        return None

    kodilog(
        f"Trailer/TMDB: selected yt_id={trailer.get('yt_id')!r} tmdb_id={tmdb_id!r} media_type={normalized_media_type!r}"
    )
    return trailer
