# -*- coding: utf-8 -*-
# resources/lib/tmdb/vod_kodi.py
#
# Sekce "VOD Premiéry" – filmy vydané na VOD za posledních 14 dní.
# Záměrně odděleno od tmdb_kodi.py (1541 řádků) pro zachování čistoty modulů.
#
# Exportuje:
#   show_vod_premieres_menu()      – submenu Česko / Globální
#   show_vod_premieres_list(params) – render výsledků s paginací

import sys
import xbmc
import xbmcgui
import xbmcplugin
import xbmcaddon
from datetime import datetime, timedelta
import time

from resources.lib.utils.log_utils import get_logger
from resources.lib.utils.ui_utils import pick_icon as ui_pick_icon, add_menu_item as ui_add_item

log = get_logger()

# ── Sdílené konstanty z tmdb_kodi (lazy import, vyhnout se cirkulárnímu importu) ──
IMAGE_BASE_URL   = 'https://image.tmdb.org/t/p/w500'
FANART_BASE_URL  = 'https://image.tmdb.org/t/p/original'

addon        = xbmcaddon.Addon('plugin.video.mmirousek_v3')
addon_handle = int(sys.argv[1])
base_url     = sys.argv[0]


def _build_url(query: dict) -> str:
    """Sestaví plugin URL z dict parametrů."""
    import urllib.parse
    return base_url + '?' + urllib.parse.urlencode(query)


def _build_url_kwargs(**kwargs) -> str:
    """Wrapper akceptující **kwargs – vyžadovaný podpis pro build_context_menu."""
    return _build_url(kwargs)


def _period_label() -> str:
    """Vrátí řetězec '16.02. – 02.03.2026' pro aktuálních 14 dní."""
    today     = datetime.now()
    date_from = (today - timedelta(days=14)).strftime('%d.%m.')
    date_to   = today.strftime('%d.%m.%Y')
    return f'{date_from} – {date_to}'


# ══════════════════════════════════════════════════════════════════════════════
# 1. SUBMENU
# ══════════════════════════════════════════════════════════════════════════════

def show_vod_premieres_menu():
    """
    Zobrazí submenu se třemi podvolbami: Filmy CZ, Globální filmy, Seriály CZ.
    Voláno z routeru akcí 'tmdb_vod_premieres_menu'.
    """
    start_time = time.perf_counter() # PROFILER_START
    from datetime import datetime, timedelta
    today     = datetime.now()
    date_from = (today - timedelta(days=60)).strftime('%d.%m.')
    date_to   = today.strftime('%d.%m.%Y')
    global_period = f'{date_from} – {date_to}'

    # ── 1. Filmy dostupné nyní (CZ) ──────────────────────────────────────────
    ui_add_item(
        handle=addon_handle,
        build_url_fn=_build_url,
        label='Filmy dostupné nyní',
        plot=(
            'Filmy aktuálně dostupné na VOD platformách v České republice:\n'
            'Netflix, Prima+, Disney+, Apple TV+, Paramount+, SkyShowtime.\n'
            'Seřazeno od nejpopulárnějších.\n'
            '(TMDb neexponuje datum přidání na streaming – nelze řadit podle VOD premiéry.)'
        ),
        action='tmdb_vod_premieres_list',
        art_icon=ui_pick_icon(addon, 'movie_popular.png', 'DefaultMovies.png', 'tmdb'),
        is_folder=True,
        region='CZ',
        media_type='movie',
        page=1
    )

    # 2. Seriály dostupné nyní (CZ) ────────────────────────────────────────
    ui_add_item(
        handle=addon_handle,
        build_url_fn=_build_url,
        label='Seriály dostupné nyní',
        plot=(
            'Seriály aktuálně dostupné na VOD platformách v České republice:\n'
            'Netflix, Prima+, Disney+, Apple TV+, Paramount+, SkyShowtime.\n'
            'Seřazeno od nejpopulárnějších.'
        ),
        action='tmdb_vod_premieres_list',
        art_icon=ui_pick_icon(addon, 'tv_popular.png', 'DefaultTVShows.png', 'tmdb'),
        is_folder=True,
        region='CZ',
        media_type='tv',
        page=1
    )

    # 3. Globální novinky (filmy) ───────────────────────────────────────────
    ui_add_item(
        handle=addon_handle,
        build_url_fn=_build_url,
        label=f'Globální – novinky ({global_period})',
        plot=(
            f'Filmy vydané na celosvětových VOD platformách v posledních 60 dnech ({global_period}).\n'
            'Seřazeno od nejnovějšího vydání.'
        ),
        action='tmdb_vod_premieres_list',
        art_icon=ui_pick_icon(addon, 'movie_top_rated.png', 'DefaultMovies.png', 'tmdb'),
        is_folder=True,
        region='GLOBAL',
        media_type='movie',
        page=1
    )

    log.info(f"TMDB_PROFILER: show_vod_premieres_menu trvalo {time.perf_counter() - start_time:.3f} s") # PROFILER_END
    xbmcplugin.endOfDirectory(addon_handle)



# ── is_latinish helper (kopie z tmdb_kodi.py) ────────────────────────────────

def _is_latinish(s: str) -> bool:
    """
    Vrátí True, pokud je text převážně latinkou (včetně českých diakritik).
    Filtruje Hangul/CJK/Cyrilici/Arabštinu – aby skin neukazoval čtverečky.
    """
    if not s:
        return False
    total_letters = latin_letters = strong_nonlatin = 0
    for ch in s:
        code = ord(ch)
        is_latin = (
            (0x0041 <= code <= 0x005A) or (0x0061 <= code <= 0x007A) or
            (0x00C0 <= code <= 0x00FF) or (0x0100 <= code <= 0x024F)
        )
        is_strong_nonlatin = (
            (0xAC00 <= code <= 0xD7AF) or (0x1100 <= code <= 0x11FF) or  # Hangul
            (0x3130 <= code <= 0x318F) or
            (0x4E00 <= code <= 0x9FFF) or (0x3400 <= code <= 0x4DBF) or  # CJK
            (0x30A0 <= code <= 0x30FF) or (0x3040 <= code <= 0x309F) or  # Kata/Hira
            (0x0400 <= code <= 0x04FF) or                                 # Cyrilice
            (0x0600 <= code <= 0x06FF)                                    # Arabština
        )
        if ch.isalpha():
            total_letters += 1
            if is_latin:
                latin_letters += 1
            if is_strong_nonlatin:
                strong_nonlatin += 1
    if total_letters == 0:
        return False
    if strong_nonlatin > 0:
        return False
    return (latin_letters / float(total_letters)) >= 0.70


# ══════════════════════════════════════════════════════════════════════════════
# 2. VÝSLEDKOVÝ SEZNAM
# ══════════════════════════════════════════════════════════════════════════════
# ── Provider ID → jméno (CZ known providers) ────────────────────────────────
_PROVIDER_NAMES = {
    8:    'Netflix',
    1184: 'Prima+',
    337:  'Disney+',
    119:  'Paramount+',
    350:  'Apple TV+',
    1773: 'SkyShowtime',
}


def _fetch_providers_batch(tmdb_ids: list, api_key: str, region: str = 'CZ') -> dict:
    """
    Vrátí {tmdb_id: ["Netflix", "Disney+", ...]} s DB cache (TTL 7 dní).
    Průběh:
      1. Načti z media.vod_providers_cz (JSON) všechny záznamy mladší 7 dní → cache_hit
      2. Pro zbývající (miss/expirované) zavolej /watch/providers paralelně
      3. Nové výsledky ulož do DB pro příští průchod
    """
    import concurrent.futures
    import requests as _req
    from datetime import datetime, timedelta

    TTL_DAYS = 7
    result   = {}
    miss_ids = []   # potřebují API volání

    # ── 1. DB cache read ─────────────────────────────────────────────────────
    try:
        from resources.lib.database.metadata_db import db as _db
        cutoff = (datetime.now() - timedelta(days=TTL_DAYS)).strftime('%Y-%m-%d %H:%M:%S')
        for tid in tmdb_ids:
            if not tid:
                continue
            try:
                row = _db.conn.execute(
                    "SELECT vod_providers_cz, vod_providers_updated_at FROM media WHERE tmdb_id = ?",
                    (tid,)
                ).fetchone()
                if row and row[0] and row[1] and row[1] > cutoff:
                    import json as _json
                    names = _json.loads(row[0])
                    if names:
                        result[tid] = names
                    # i prázdný seznam = validní cache hit (film prostě čeká na žádné platformě)
                    # přeskočíme API volání
                else:
                    miss_ids.append(tid)
            except Exception:
                miss_ids.append(tid)
    except Exception as e:
        log.warning(f'[VOD Premiéry] DB cache read error: {e}')
        miss_ids = [tid for tid in tmdb_ids if tid]

    log.info(f'[VOD Premiéry] providers cache: {len(result)} hits, {len(miss_ids)} miss → API')

    if not miss_ids:
        return result

    # ── 2. API volání pro miss ────────────────────────────────────────────────
    def _fetch_one(tmdb_id):
        try:
            url = f'https://api.themoviedb.org/3/movie/{tmdb_id}/watch/providers'
            r = _req.get(url, params={'api_key': api_key}, timeout=5)
            r.raise_for_status()
            flatrate = r.json().get('results', {}).get(region, {}).get('flatrate', [])
            names = [_PROVIDER_NAMES.get(p.get('provider_id'), p.get('provider_name', '')) for p in flatrate]
            return tmdb_id, [n for n in names if n]
        except Exception:
            return tmdb_id, None  # None = API selhalo, neukládáme do cache

    api_results = {}
    try:
        with concurrent.futures.ThreadPoolExecutor(max_workers=5) as ex:
            futures = {ex.submit(_fetch_one, tid): tid for tid in miss_ids}
            for future in concurrent.futures.as_completed(futures, timeout=8):
                try:
                    tid, names = future.result(timeout=1)
                    if names is not None:
                        api_results[tid] = names
                        if names:
                            result[tid] = names
                except Exception:
                    pass
    except Exception as e:
        log.warning(f'[VOD Premiéry] providers batch API error: {e}')

    # ── 3. DB cache write ─────────────────────────────────────────────────────
    if api_results:
        import json as _json
        now_str = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        try:
            for tid, names in api_results.items():
                _db.conn.execute(
                    """UPDATE media SET vod_providers_cz = ?, vod_providers_updated_at = ?
                       WHERE tmdb_id = ?""",
                    (_json.dumps(names, ensure_ascii=False), now_str, tid)
                )
            _db.conn.commit()
            log.info(f'[VOD Premiéry] providers uloženy do DB: {len(api_results)} záznamů')
        except Exception as e:
            log.warning(f'[VOD Premiéry] DB cache write error: {e}')

    return result



def show_vod_premieres_list(params: dict):
    """
    Zobrazí seznam filmů vydaných na VOD.

    Parametry (z URL):
        region : 'CZ' nebo 'GLOBAL'
        page   : číslo stránky (výchozí 1)

    Voláno z routeru akcí 'tmdb_vod_premieres_list'.
    """
    start_time = time.perf_counter() # PROFILER_START
    log.info(f'[VOD Premiéry] ENTER params={params}')

    handle = int(sys.argv[1])
    addon_local = xbmcaddon.Addon('plugin.video.mmirousek_v3')

    # ── Parametry ────────────────────────────────────────────────────────────
    region     = (params.get('region') or 'CZ').upper()
    media_type = (params.get('media_type') or 'movie').lower()  # 'movie' nebo 'tv'
    try:
        page = int(params.get('page', 1))
    except Exception:
        page = 1

    # ── API klíč ─────────────────────────────────────────────────────────────
    api_key = addon_local.getSetting('tmdb_api_key')
    if not api_key:
        xbmcgui.Dialog().notification(
            'TMDb chyba', 'Chybí TMDb API klíč v nastavení doplňku.',
            xbmcgui.NOTIFICATION_WARNING, 3000
        )
        xbmcplugin.endOfDirectory(handle, succeeded=False)
        return

    # ── API volání ────────────────────────────────────────────────────────────
    from resources.lib.tmdb.tmdb_module import TMDb
    tmdb = TMDb(api_key)

    try:
        result = tmdb.discover_vod_premieres_page(region=region, page=page, media_type=media_type)
    except Exception as e:
        log.error(f'[VOD Premiéry] API chyba: {e}')
        xbmcgui.Dialog().notification('TMDb chyba', f'Chyba VOD: {e}', xbmcgui.NOTIFICATION_ERROR, 3000)
        xbmcplugin.endOfDirectory(handle, succeeded=False)
        return

    if not result or not isinstance(result, tuple) or len(result) != 3:
        log.error('[VOD Premiéry] discover_vod_premieres_page() nevrátil (items, total_pages, page_size)')
        xbmcgui.Dialog().notification('TMDb', 'Interní chyba VOD. Viz log.', xbmcgui.NOTIFICATION_ERROR, 3000)
        xbmcplugin.endOfDirectory(handle, succeeded=False)
        return

    items, total_pages, page_size = result

    if not items:
        log.info(f'[VOD Premiéry] Žádné výsledky: region={region} page={page}')
        xbmcgui.Dialog().notification('TMDb', 'Žádné VOD novinky pro zvolenou oblast.', xbmcgui.NOTIFICATION_INFO, 2500)
        xbmcplugin.endOfDirectory(handle)
        return

    # ── Paralelní fetch watch/providers – vždy s watch_region=CZ (uživatel je v ČR) ──
    # Pro CZ sekci: filmy jsou přefiltrované na CZ poskytovatele, takže téměř vždy hit.
    # Pro GLOBAL sekci: globální filmy – ukáže které z nich jsou dostupné i v ČR.
    tmdb_ids_for_providers = [item.get('id') for item in items if item.get('id')]
    providers_map = _fetch_providers_batch(tmdb_ids_for_providers, api_key, region='CZ')
    log.info(f'[VOD Premiéry] providers_map loaded: {len(providers_map)} hits (region={region})')

    # ── Nastavení contentu ────────────────────────────────────────────────────
    if media_type == 'tv':
        type_label = 'Seriály'
        kodi_content = 'tvshows'
    else:
        type_label = 'Filmy'
        kodi_content = 'movies'
    region_label = 'dostupné nyní (CZ)' if region == 'CZ' else 'novinky 60 dní (Globální)'
    xbmcplugin.setPluginCategory(handle, f'VOD Premiéry • {type_label} {region_label} • str. {page}')
    xbmcplugin.setContent(handle, kodi_content)

    # ── Lazy importy ─────────────────────────────────────────────────────────
    from resources.lib.tmdb.tmdb_kodi import set_video_info
    try:
        from resources.lib.tmdb.tmdb_utils import get_english_title
        _en_ok = True
    except Exception as e:
        log.warning(f'[VOD Premiéry] get_english_title nedostupný: {e}')
        _en_ok = False

    try:
        from resources.lib.database.metadata_db import db
        _db_ok = True
    except Exception as e:
        log.warning(f'[VOD Premiéry] DB nedostupná: {e}')
        _db_ok = False

    try:
        from resources.lib.utils.context_builder import build_context_menu
        _ctx_ok = True
    except Exception as e:
        log.warning(f'[VOD Premiéry] context_builder nedostupný: {e}')
        _ctx_ok = False

    # ── Render položek ────────────────────────────────────────────────────────
    directory_items = []
    
    for item in items:
        try:
            tmdb_id       = item.get('id')
            label_cz_raw  = item.get('label') or ''
            label_origin  = (item.get('original_label') or '').strip()
            origin_lang   = (item.get('original_language') or 'en').lower()
            year_txt      = item.get('year') or ''
            rating_val    = 0.0
            try:
                rating_val = float(item.get('rating') or 0.0)
            except Exception:
                pass

            poster_path   = item.get('poster_path') or ''
            backdrop_path = item.get('backdrop_path') or ''

            # ── EN fallback z DB/API (shodná logika jako v tmdb_kodi) ────────
            en_title = None
            if _en_ok and tmdb_id:
                try:
                    # DŮLEŽITÉ: media_type musí odpovídat – TMDb má oddělené ID prostory
                    # pro filmy ('movie') a seriály ('tv'). Záměna vrátí EN název jiného titulu!
                    en_title = get_english_title(media_type, tmdb_id)
                except Exception as e:
                    log.warning(f'[VOD Premiéry] get_english_title selhalo tmdb_id={tmdb_id}: {e}')

            label_cz = label_cz_raw.strip() if label_cz_raw else ''
            label_en = str(en_title).strip() if en_title else ''

            # ── DB fallback na title_cs ──────────────────────────────────────
            # Spustí se ve třech případech:
            #  a) label_cz je prázdný (TMDb nevrátil překlad)
            #  b) label_cz existuje ale není latinkou (korejský/čínský/... název)
            #  c) label_cz == label_en → TMDb nemá CZ překlad, vrátil EN jako cs-CZ fallback
            #     → ve všech případech zkus DB, kde může být uložen CZ název z předchozích session
            _cz_same_as_en = (label_cz and label_en and label_cz.lower() == label_en.lower())
            _need_db_fallback = (not label_cz) or (not _is_latinish(label_cz)) or _cz_same_as_en
            if _need_db_fallback and _db_ok and tmdb_id:
                try:
                    row = db.get(tmdb_id)
                    db_title_cs = (row.get('title_cs') or '') if row else ''
                    # Použijeme DB název jen pokud:
                    # – je latinkou (nezobrazíme čtverečky)
                    # – liší se od EN názvu (= opravdu CZ, ne jen EN kopie)
                    if db_title_cs and _is_latinish(db_title_cs) and db_title_cs.lower() != label_en.lower():
                        label_cz = db_title_cs
                        log.debug(f'[VOD Premiéry] DB fallback title_cs pro tmdb_id={tmdb_id}: "{label_cz}"')
                except Exception:
                    pass

            # ── Výběr primárního/sekundárního názvu + is_latinish guard ─────
            # CZ prioritní pokud je latinkou, jinak EN (zamezí korejským/čínským čtverečkům)
            if label_cz and _is_latinish(label_cz):
                primary_label   = label_cz
                secondary_label = label_en if (label_en and label_en != primary_label) else None
            else:
                if label_cz and not _is_latinish(label_cz):
                    log.info(f'[VOD Premiéry] CZ label není latinkou → EN fallback (tmdb_id={tmdb_id}): "{label_cz}"')
                # EN fallback; pokud ani EN, zkusíme originál (jen pokud je latinkou)
                primary_label   = label_en or (label_origin if _is_latinish(label_origin) else 'Bez názvu')
                secondary_label = label_cz if (label_cz and _is_latinish(label_cz) and label_cz != primary_label) else None

            # ── Sestavení display labelu ─────────────────────────────────────
            display_label = primary_label
            if secondary_label and secondary_label != primary_label:
                display_label += f' [COLOR grey][{secondary_label}][/COLOR]'
            if year_txt:
                display_label += f' ({year_txt})'
            if rating_val > 0.0:
                display_label += f' [COLOR=FFFFFFFF]★[/COLOR][COLOR=FFFFD700]{rating_val:.1f}[/COLOR]'
            # VOD provider suffix (jen CZ)
            if tmdb_id and tmdb_id in providers_map:
                provider_str = ', '.join(providers_map[tmdb_id])
                display_label += f' [COLOR steelblue][{provider_str}][/COLOR]'

            li = xbmcgui.ListItem(label=display_label)

            # ── Artwork ──────────────────────────────────────────────────────
            if poster_path:
                li.setArt({
                    'icon':   IMAGE_BASE_URL + poster_path,
                    'thumb':  IMAGE_BASE_URL + poster_path,
                    'poster': IMAGE_BASE_URL + poster_path,
                })
            if backdrop_path:
                li.setArt({'fanart': FANART_BASE_URL + backdrop_path})

            # ── InfoTagVideo ─────────────────────────────────────────────────
            info_labels = {
                'title':     primary_label,
                'plot':      item.get('plot') or '',
                'rating':    rating_val,
                'mediatype': 'movie',
            }
            if year_txt and str(year_txt).isdigit():
                info_labels['year'] = int(year_txt)
            info_labels = {k: v for k, v in info_labels.items() if v not in (None, '')}
            set_video_info(li, info_labels)

            # ── DB uložení (jen CZ/EN; jiné jazyky se neukládají) ───────────
            if _db_ok and tmdb_id:
                try:
                    title_cs_for_db = primary_label if origin_lang == 'cs' else (label_cz if _is_latinish(label_cz) else None)
                    title_en_for_db = label_en or (primary_label if origin_lang == 'en' else None)
                    db.update(
                        tmdb_id,
                        {
                            'media_type':    'movie',
                            'title_cs':      title_cs_for_db,
                            'title_en':      title_en_for_db,
                            'year':          year_txt or None,
                            'poster_path':   poster_path or None,
                            'backdrop_path': backdrop_path or None,
                        },
                        source='vod_premieres'
                    )
                except Exception as e:
                    log.warning(f'[VOD Premiéry] DB update failed tmdb_id={tmdb_id}: {e}')

            # ── Kontextové menu ──────────────────────────────────────────────
            if _ctx_ok and tmdb_id:
                try:
                    ctx_contexts = ['trakt_tv_default', 'tmdb_csfd'] if media_type == 'tv' else ['trakt_movies_default', 'tmdb_csfd']
                    item_data = {'movie_name': primary_label, 'tmdb_id': tmdb_id}
                    cm = build_context_menu(_build_url_kwargs, item_data, contexts=ctx_contexts)
                    if cm:
                        li.addContextMenuItems(cm, replaceItems=True)
                except Exception as e:
                    log.warning(f'[VOD Premiéry] context_menu error: {e}')

            # ── URL: click akce dle media_type ───────────────────────────────
            title_cs_for_db = primary_label if origin_lang == 'cs' else (label_cz if _is_latinish(label_cz) else None)
            title_en_for_db = label_en or (primary_label if origin_lang == 'en' else None)
            if media_type == 'tv':
                # Seriál → výběr sezóny
                url = _build_url({
                    'action':    'tmdb_seasons',
                    'tmdb_id':   str(tmdb_id or ''),
                    'cz_title':  title_cs_for_db or '',
                    'eng_title': title_en_for_db or '',
                    'year':      year_txt or '',
                    'mediatype': 'tv',
                })
            else:
                # Film → hledání na Webshare
                url = _build_url({
                    'action':    'show_search_dialog',
                    'cz_title':  title_cs_for_db or '',
                    'eng_title': title_en_for_db or '',
                    'year':      year_txt or '',
                    'tmdb_id':   str(tmdb_id or ''),
                    'mediatype': 'movie',
                })
            directory_items.append((url, li, True))

        except Exception as e:
            import traceback
            log.error(f'[VOD Premiéry] render error tmdb_id={item.get("id")}: {traceback.format_exc()}')
            continue

    # ── DB commit ────────────────────────────────────────────────────────────
    if _db_ok:
        try:
            db.conn.commit()
        except Exception as e:
            log.error(f'[VOD Premiéry] DB COMMIT error: {e}')

    # ── Paginace ──────────────────────────────────────────────────────────────
    display_total = str(total_pages) if total_pages else '?'
    try:
        has_more = int(page) < int(total_pages or 1)
    except Exception:
        has_more = len(items) >= 20

    if has_more:
        next_url = _build_url({
            'action':     'tmdb_vod_premieres_list',
            'region':     region,
            'media_type': media_type,
            'page':       str(page + 1),
        })
        li_next = xbmcgui.ListItem(label=f'[COLOR gold]Další strana » ({page + 1}/{display_total})[/COLOR]')
        li_next.setArt({'icon': 'DefaultFolder.png'})
        directory_items.append((next_url, li_next, True))

    xbmcplugin.addDirectoryItems(handle, directory_items)

    log.info(f'[VOD Premiéry] END region={region} page={page}/{total_pages} items={len(items)}')
    log.info(f"TMDB_PROFILER: show_vod_premieres_list trvalo {time.perf_counter() - start_time:.3f} s") # PROFILER_END
    xbmcplugin.endOfDirectory(handle, succeeded=True, cacheToDisc=False)
