# -*- coding: utf-8 -*-
# resources/lib/tmdb/tmdb_module.py
# TMDb modul pro mmirousek_v2 – plně přes SQLite DB (metadata_db)

import requests
import xbmc
from requests.exceptions import HTTPError
from functools import lru_cache
import concurrent.futures
from resources.lib.utils.log_utils import get_logger

log = get_logger()

# Centrální SQLite DB
from resources.lib.database.metadata_db import db

API_URL = 'https://api.themoviedb.org/3'
IMAGE_BASE_URL_POSTER = 'https://image.tmdb.org/t/p/w500'
IMAGE_BASE_URL_FANART = 'https://image.tmdb.org/t/p/original'

# Seznamy – stejné jako dřív
TMDB_BASIC_LISTS = {
    'movie_popular':     {'tmdb_type': 'movie', 'path': '/movie/popular'},
    'tv_top_rated':      {'tmdb_type': 'tv',    'path': '/tv/top_rated'},
    'movie_upcoming':    {'tmdb_type': 'movie', 'path': '/movie/upcoming'},
    'tv_on_the_air':     {'tmdb_type': 'tv',    'path': '/tv/on_the_air'},
    'tv_popular':        {'tmdb_type': 'tv',    'path': '/tv/popular'},
    'movie_top_rated':   {'tmdb_type': 'movie', 'path': '/movie/top_rated'},
    'tv_airing_today':   {'tmdb_type': 'tv',    'path': '/tv/airing_today'},
    'trending_day':      {'tmdb_type': 'all',   'path': '/trending/all/day'},
    'person_popular':       {'tmdb_type': 'person', 'path': '/person/popular'},
    'person_trending_day':  {'tmdb_type': 'person', 'path': '/trending/person/day'},
    'person_trending_week': {'tmdb_type': 'person', 'path': '/trending/person/week'},
}

class TMDb:
    def __init__(self, api_key):
        self.api_key = api_key

    # ────────────────────── ZÁKLADNÍ VOLÁNÍ API ──────────────────────
    def _call_api_raw(self, full_url, extra_params=None):
        if extra_params is None:
            extra_params = {}
        
        params = {
            'api_key': self.api_key,
            # Výchozí language, které bude přepsáno v params.update(), pokud je v extra_params
            'language': 'cs-CZ', 
        }
        
        # extra_params (který nyní obsahuje 'language': 'en-US' pro osoby)
        params.update(extra_params) 
        
        # Sestavení finální URL pro debug účely
        import requests 
        try:
            # 🟢 Ponecháme debug logování na INFO úrovni
            final_url_with_params = requests.Request('GET', full_url, params=params).prepare().url
            log.info(f"TMDb INFO: Finální API URL pro dotaz '{full_url}' -> {final_url_with_params}")
        except Exception as e:
            log.error(f"[TMDb] Chyba při sestavování debug URL: {e}")

        try:
            r = requests.get(full_url, params=params, timeout=12)
            r.raise_for_status()
            return r
        except Exception as e:
            log.error(f"[TMDb] RAW call error: {e}")
            raise

    def _call_api(self, api_path, page=1, extra_params=None):
        if extra_params is None:
            extra_params = {}
        final_params = {'page': page}
        final_params.update(extra_params)
        return self._call_api_raw(f"{API_URL}{api_path}", final_params)
    def call(self, category_key, query=None, page=1):
        extra_params = {}
        
        # 🟢 1. Zjistíme, zda jde o seznam OSOB
        is_person_list = category_key in ('search_person', 'person_popular', 'person_trending_day', 'person_trending_week')

        # 2. Nastavíme api_path
        if category_key == 'search':
            if not query:
                raise ValueError("Chybí vyhledávací dotaz")
            api_path = "/search/multi"
            extra_params['query'] = query
        elif category_key == 'search_person':
            if not query:
                raise ValueError("Chybí vyhledávací dotaz")
            api_path = "/search/person"
            extra_params['query'] = query
        elif category_key in TMDB_BASIC_LISTS:
            api_path = TMDB_BASIC_LISTS[category_key]['path']
        else:
            raise ValueError(f"Neznámá kategorie: {category_key}")

        # 🚨 KLÍČOVÁ ZMĚNA: Přepíšeme language na en-US, protože cs-CZ u popular/person nefunguje
        if is_person_list:
            extra_params['language'] = 'en-US' # Přepíšeme lokální jazyk globálním (funkčním)

        return self._call_api(api_path, page=page, extra_params=extra_params)
    def get_person_detail(self, person_id: int):
        """
        Načte detail osoby včetně oddělených credits a image profilů.
        Pokud CZ lokalizace nevrátí biografii, zkusí EN fallback.
        """
        api_path = f"/person/{person_id}"
        
        extra_params = {
            'append_to_response': 'translations,movie_credits,tv_credits,images'
        }
        
        try:
            response = self._call_api(api_path, page=1, extra_params=extra_params)
            data = response.json()

            if not (data.get('biography') or '').strip():
                try:
                    response_en = self._call_api(
                        api_path,
                        page=1,
                        extra_params={
                            'append_to_response': 'translations,movie_credits,tv_credits,images',
                            'language': 'en-US'
                        }
                    )
                    data_en = response_en.json() or {}
                    biography_en = (data_en.get('biography') or '').strip()
                    if biography_en:
                        data['biography'] = biography_en
                    if not data.get('images') and data_en.get('images'):
                        data['images'] = data_en.get('images')
                except Exception as fallback_error:
                    log.warning(f"TMDb WARNING: EN fallback pro osobu {person_id} selhal → {fallback_error}")

            return data
        except Exception as e:
            log.error(f"TMDb EXCEPTION: Chyba při načítání detailu osoby {person_id} → {e}")
            return None
    
    # ────────────────────── EXTERNAL IDS (s DB cache) ──────────────────────
    @lru_cache(maxsize=256)
    def get_movie_external_ids(self, tmdb_id):
        return self._get_external_ids(tmdb_id, 'movie')

    @lru_cache(maxsize=256)
    def get_tv_external_ids(self, tmdb_id):
        return self._get_external_ids(tmdb_id, 'tv')

    def _get_external_ids(self, tmdb_id, media_type):
        """
        Vrátí external_ids (především imdb_id) s prioritou:
        1. Z centrální SQLite DB (metadata_db)
        2. Z TMDb API → uloží do DB
        """
        # 1. Nejrychlejší – z DB
        cached = db.get(tmdb_id)
        if cached and cached.get('imdb_id'):
            # Bonus: aktualizujeme last_accessed
            try:
                db.conn.execute(
                    "UPDATE media SET last_accessed = CURRENT_TIMESTAMP WHERE tmdb_id = ?",
                    (tmdb_id,)
                )
                db.conn.commit()
            except:
                pass
            return {'imdb_id': cached['imdb_id']}

        # 2. Není v DB → voláme API
        try:
            path = f"/{media_type}/{tmdb_id}/external_ids"
            data = self._call_api_raw(API_URL + path).json()
            imdb_id = data.get('imdb_id')

            if imdb_id:
                # Ukládáme do DB včetně media_type (KLÍČOVÉ!)
                db.update(tmdb_id, {
                    'imdb_id': imdb_id,
                    'media_type': media_type
                }, source='tmdb')

            return data

        except Exception as e:
            log.warning(f"[TMDb] external_ids error {media_type}/{tmdb_id}: {e}")
            return {}

    def get_external_ids_bulk(self, ids, media_type='movie'):
        """Hromadné načítání – nejprve z DB, pak asynchronně z API přes ThreadPool"""
        if not ids:
            return {}

        results = {}
        to_fetch = []

        for tmdb_id in ids:
            # 1. Zkusíme z DB (rychle)
            cached = db.get(tmdb_id)
            if cached and cached.get('imdb_id'):
                results[tmdb_id] = {'imdb_id': cached['imdb_id']}
            else:
                to_fetch.append(tmdb_id)

        # 2. Není v DB → voláme API v paralelních vláknech
        if to_fetch:
            func = self.get_movie_external_ids if media_type == 'movie' else self.get_tv_external_ids
            
            def fetch_single(tid):
                try:
                    return tid, func(tid)
                except Exception:
                    return tid, {}

            with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
                pool_results = executor.map(fetch_single, to_fetch)
                for tid, data in pool_results:
                    results[tid] = data

        return results
    # ────────────────────── NAČÍTÁNÍ SEZNAMŮ (ponecháváme původní) ──────────────────────
    def get_list(self, list_key, query=None, max_pages=3):
        """Původní implementace – zatím beze změny (používá se v tmdb_kodi.py)"""
        # if list_key != 'search' and list_key not in TMDB_BASIC_LISTS:
        #     log.error(f"TMDb ERROR: Neznámý klíč seznamu → {list_key}")
        #     return []

        all_results = []
        processor = ListBasic(tmdb_api=self)

        for page in range(1, max_pages + 1):
            try:
                response = self.call(list_key, query=query, page=page)
                data = response.json()
                page_results = processor.process_results(data)
                all_results.extend(page_results)
                if page >= data.get('total_pages', 1):
                    break
            except Exception as e:
                log.error(f"TMDb EXCEPTION: Stránka {page} selhala → {e}")
                break
        return all_results
    
    # --- nové: stránkované načtení jedné TMDb strany ---
    def get_list_page(self, list_key, query=None, page=1):
        """
        Vrátí položky pouze pro danou stránku + total_pages + page_size.
        Zachovává procesor ListBasic, jazykové přepínače z call().
        """
        response = self.call(list_key, query=query, page=page)      # využívá váš call() s page
        data = response.json()                                       # TMDb odpověď obsahuje 'page', 'total_pages', 'results'
        processor = ListBasic(tmdb_api=self)
        items = processor.process_results(data)                      # stejné pole jako dříve (id, media_type, label, …)
        total_pages = int(data.get('total_pages', 1))
        page_size = len(data.get('results', []))                     # typicky 20
        return items, total_pages, page_size
    
    def discover_movies_page(self, genre_id=None, year=None, from_year=None, to_year=None,
                            min_vote=None, page=1, language='cs-CZ', sort_by='popularity.desc'):
        extra = {'language': language, 'sort_by': sort_by}

        # Žánr
        if genre_id:
            try:
                extra['with_genres'] = str(int(genre_id))
            except Exception:
                extra['with_genres'] = str(genre_id)

        # Rok vs. rozpětí
        if year and (not from_year and not to_year):
            try:
                extra['primary_release_year'] = int(year)
            except Exception:
                pass
        else:
            if from_year:
                try:
                    extra['primary_release_date.gte'] = f"{int(from_year)}-01-01"
                except Exception:
                    pass
            if to_year:
                try:
                    extra['primary_release_date.lte'] = f"{int(to_year)}-12-31"
                except Exception:
                    pass

        # Rating
        if min_vote not in (None, '', 'None'):
            try:
                extra['vote_average.gte'] = float(min_vote)
            except Exception:
                pass

        # Volání
        response = self._call_api("/discover/movie", page=page, extra_params=extra)
        data = response.json()
        processor = ListBasic(tmdb_api=self)
        items = processor.process_results(data)
        total_pages = int(data.get('total_pages', 1))
        page_size = len(data.get('results', []))
    
        # DEBUG pro log – ať víš přesně co se posílá a vrací
        log.info(f"[TMDb Discover] params={extra} page={page} results={page_size} total_pages={total_pages}")
        return items, total_pages, page_size

    def discover_vod_premieres_page(self, region='CZ', page=1, language='cs-CZ', media_type='movie'):
        """
        /discover/{media_type} filtrovaný na VOD dostupnost.
        media_type: 'movie' nebo 'tv'
        region='CZ'     → bez datumového filtru, sort popularity.desc – „Co je teď dostupné na CZ VOD"
        region='GLOBAL' → 60denní okno release_date, sort release_date.desc (pouze filmy)
        Vrací (items, total_pages, page_size).
        """
        from datetime import datetime, timedelta
        today = datetime.now()

        api_path = f'/discover/{media_type}'

        extra = {
            'language': language,
            'include_adult': 'false',
            'with_watch_monetization_types': 'flatrate',
        }

        if region == 'CZ':
            # Bez datumového omezení – vše dostupné na CZ platformách, seřazeno popularitou
            extra['sort_by'] = 'popularity.desc'
            extra['watch_region'] = 'CZ'
            # Netflix=8, Prima+=1184, Disney+=337, Apple TV+=350, Paramount+=119, SkyShowtime=1773
            extra['with_watch_providers'] = '8|1184|337|119|350|1773'
        else:
            # GLOBAL: okno 60 dní (jen filmy), seřazeno od nejnovějšího
            date_from = (today - timedelta(days=60)).strftime('%Y-%m-%d')
            date_to   = today.strftime('%Y-%m-%d')
            extra['sort_by'] = 'primary_release_date.desc'
            extra['primary_release_date.gte'] = date_from
            extra['primary_release_date.lte'] = date_to

        response = self._call_api(api_path, page=page, extra_params=extra)
        data = response.json()
        processor = ListBasic(tmdb_api=self)
        items = processor.process_results(data)
        total_pages = int(data.get('total_pages', 1))
        page_size = len(data.get('results', []))
        log.info(f'[VOD Premiéry] media_type={media_type} region={region} page={page} results={page_size} total_pages={total_pages}')
        return items, total_pages, page_size


# ────────────────────── ZPRACOVÁNÍ VÝSLEDKŮ PRO KODI (stejné jako dřív) ──────────────────────
class ListBasic:
    def __init__(self, tmdb_api):
        self.tmdb_api = tmdb_api

    def process_results(self, data):
        results = []
        for item in data.get('results', []):
            
            # 1. ROBUSTNÍ DETEKCE OSOBY:
            # Objekt osoby má vždy 'known_for_department' nebo 'profile_path', film/seriál ne.
            is_person = 'known_for_department' in item or 'profile_path' in item
            
            if is_person:
                media_type = 'person'
            else:
                # Původní detekce pro filmy/seriály (pro multi-search)
                media_type = item.get('media_type', 'movie' if 'title' in item else 'tv')

            
            # 🟢 LOGIKA: Zpracování OSOB (Použije se i pro person_popular)
            if media_type == 'person':
                result = {
                    'id': item.get('id'),
                    'media_type': 'person', 
                    'label': item.get('name') or "Neznámá osoba",
                    'original_label': item.get('original_name'),
                    'profile_path': item.get('profile_path'),
                    'known_for': item.get('known_for', []) 
                }
                # Ponecháme jen kontrolu na základní údaje, obrázek je volitelný
                if result['label'] and result['id']: 
                    results.append(result)
                continue # Skip the rest of the function for persons
            
            # 🛑 PŮVODNÍ LOGIKA: Zpracování filmů/seriálů (vyžaduje poster_path)
            result = {
                'id': item.get('id'),
                'media_type': media_type,
                'label': item.get('title') or item.get('name') or "Bez názvu",
                'original_label': item.get('original_title') or item.get('original_name'),
                'original_language': item.get('original_language'),
                'plot': item.get('overview') or "",
                'rating': item.get('vote_average') or 0.0,
                'year': (item.get('release_date') or item.get('first_air_date') or '').split('-')[0],
                'poster_path': item.get('poster_path'), # Zde by objekt osoby selhal
                'backdrop_path': item.get('backdrop_path'),
            }
            # Check for required fields for movies/tv
            if result['label'] and result['poster_path']:
                results.append(result)
        return results
