# -*- coding: utf-8 -*-
import io
import os
import json
import re
import html
import xbmc
import xbmcgui
import xbmcplugin
import xbmcvfs
import sys
from urllib.parse import parse_qs, urlparse
from typing import Optional, Dict, Any # 🚨 NOVÝ IMPORT pro type hinting

from xml.etree import ElementTree as ET
from resources.lib.utils.ui_utils import clean_filename, ensure_folder, make_target_path
from resources.lib.utils.log_utils import get_logger

log = get_logger()
_POST_PLAY_RETURN_PROP = 'sm3_post_play_return_url'


def _normalize_plugin_return_url(url: str) -> str:
    raw = str(url or '').strip().strip('"')
    if not raw or raw.lower() == 'none':
        return ''
    raw = html.unescape(raw).replace('&amp;', '&')
    if not raw.startswith('plugin://plugin.video.mmirousek_v3'):
        return ''
    return raw


def _extract_action(url: str) -> str:
    try:
        return (parse_qs(urlparse(url).query).get('action') or [''])[0]
    except Exception:
        return ''


def _alarmclock_safe_url(url: str) -> str:
    return str(url or '').replace(',', '%2C').replace('"', '%22').replace('|', '%7C')

# ──────────────────────────────────────────────────────────────────────────────
# Historie vyhledávání (napojeno na SQLite)
# ──────────────────────────────────────────────────────────────────────────────
def loadsearch(profile=None, history_file_name='search_history'):
    """Načte historii vyhledávání z SQLite databáze."""
    try:
        from resources.lib.database.metadata_db import db
        return db.load_search_queries()
    except Exception as e:
        log.error(f"Chyba při načítání historie vyhledávání z DB: {e}")
        return []

def storesearch(what, profile=None, addon=None, history_file_name='search_history'):
    """Uloží dotaz do historie v SQLite (omezeno nastavením shistory)."""
    if not what:
        return
        
    size = 20
    if addon:
        # Původně načítáno ze settings (shistory), nyní pevná hodnota pro V3
        size = 20

    try:
        from resources.lib.database.metadata_db import db
        db.save_search_query(what, max_items=size)
    except Exception as e:
        log.error(f"Chyba při ukládání historie vyhledávání do DB: {e}")

def removesearch(what, profile=None, history_file_name='search_history'):
    """Odstraní položku z historie vyhledávání v SQLite."""
    if not what:
        return
    try:
        from resources.lib.database.metadata_db import db
        db.remove_search_query(what)
    except Exception as e:
        log.error(f"Chyba při mazání položky z historie v DB: {e}")

# ──────────────────────────────────────────────────────────────────────────────
# Hledání na Webshare (plná 1:1 logika, předáváme vše jako argumenty)
# ──────────────────────────────────────────────────────────────────────────────
# 🚨 ZMĚNA 1: Přidání tmdb_id a mediatype do signatury
def dosearch(token, what, category, sort, limit, offset, action,
             addon, handle, get_url, api, revalidate, popinfo,
             none_placeholder='%#NONE#%', 
                          tmdb_id: Optional[str] = None, 
             mediatype: Optional[str] = None):
    log.info(f"dosearch(): what={what}, tmdb_id={tmdb_id}, mediatype={mediatype}, category={category}, sort={sort}, limit={limit}, offset={offset}")
    log.info(f"dosearch(): Přijato → what={what}, tmdb_id={tmdb_id}, mediatype={mediatype}, category={category}, offset={offset}")

    # — 1) PRVNÍ POKUS: bez tokenu (guest) —
    data = {
        'what': '' if what == none_placeholder else what,
        'category': category,
        'sort': sort,
        'limit': limit,
        'offset': offset,
        'maybe_removed': 'true'
    }
    response = api('search', data)
    try:
        xml = ET.fromstring(response.content)
    except Exception as e:
        log.error(f"ERROR search parse (guest): {e}")
        xml = None

    ok = (xml is not None) and (xml.find('status') is not None) and (xml.find('status').text == 'OK')

    # — 2) TICHÝ RETRY: pokus o login/revalidate + druhý pokus s wst —
    if not ok:
        try:
            _token = revalidate()
        except Exception as e:
            log.error(f"revalidate() failed: {e}")
            _token = None
        if _token:
            data['wst'] = _token
            response = api('search', data)
            try:
                xml = ET.fromstring(response.content)
            except Exception as e:
                log.error(f"ERROR search parse (retry): {e}")
                xml = None
            ok = (xml is not None) and (xml.find('status') is not None) and (xml.find('status').text == 'OK')

    if not ok:
        popinfo('Vznikla chyba při komunikaci s Webshare API.', icon=xbmcgui.NOTIFICATION_WARNING)
        xbmcplugin.endOfDirectory(handle, succeeded=True)
        return

    # — zpracování výsledků —
    results = []
    for file in xml.iter('file'):
        item = {}
        for e in file:
            item[e.tag] = e.text
        results.append(item)

    def quality_score(item):
        score = 0
        q = (item.get('quality') or '').lower()
        info = (item.get('ainfo') or '').lower()
        if '2160' in q or '4k' in q: score += 100
        elif '1080' in q: score += 80
        elif '720' in q: score += 50
        else: score += 20
        for feature in ['hdr', 'dolby vision', 'dv', 'hevc', 'x265']:
            if feature in q or feature in info:
                score += 10
        lang = (item.get('lang') or '').lower()
        if 'cz' in lang or 'cs' in lang:
            score += 20
        try:
            size = float(item.get('size', 0))
            score += size / (1024 * 1024 * 100)
        except:
            pass
        return score

    results.sort(key=lambda x: quality_score(x), reverse=True)
    log.info(f"Počet nalezených souborů: {len(results)}")

    for item in results:
        ws_name = item.get('name', '') or ''
        target_path = make_target_path(addon, ws_name)

        # Kontextové menu: Přidat do fronty
        from resources.lib.utils.context_builder import build_context_menu
        item_data = {
            'file_ident': item['ident'],
            'file_name': ws_name,
            'file_size': item.get('size', '0'),
            'target_path': target_path,
            'tmdb_id': tmdb_id,
            'ws_mediatype': mediatype or 'movie',
        }
        commands = build_context_menu(
            get_url,
            item_data,
            contexts=['webshare_search_add_queue', 'titulky_ws_file'],
        )

        try:
            size_bytes = float(item.get('size', 0))
            size_gb_str = f"{size_bytes / (1024**3):.2f} GB" if size_bytes > 0 else "?"
        except:
            size_gb_str = "?"

        label = f"{item.get('name')} ({size_gb_str})"
        li = xbmcgui.ListItem(label=label)
        tag = li.getVideoInfoTag()
        tag.setTitle(label)
        li.setProperty('IsPlayable', 'true')
        
        if commands:
            li.addContextMenuItems(commands, replaceItems=True)

        # 🚨 ZMĚNA 2: Přidání tmdb_id a mediatype do URL pro action='play'
        # play_url_params: Dict[str, Any] = {'action': 'play', 'ident': item['ident'], 'name': item['name']}
        play_url_params: Dict[str, Any] = {'action': 'play', 'ident': item['ident']}
        if tmdb_id:
            play_url_params['tmdb_id'] = tmdb_id
        if mediatype:
            play_url_params['mediatype'] = mediatype
            
        xbmcplugin.addDirectoryItem(
            handle,
            get_url(**play_url_params),
            li, False
        )

    xbmcplugin.endOfDirectory(handle)

# ──────────────────────────────────────────────────────────────────────────────
# Kořen vyhledávání (UI) – plná verze, bez globálů
# ──────────────────────────────────────────────────────────────────────────────
# 🚨 ZMĚNA 3: Přidání tmdb_id a mediatype do signatury, předání backend závislostí
def show_search_dialog(addon, handle, profile, get_url_fn, api, revalidate, popinfo,
                       cz_title: str, eng_title: str, year: str, 
                       tmdb_id: Optional[str] = None, mediatype: Optional[str] = None,
                       cancel_return_url: str = '',
                       return_after_play_url: str = ''):
    """
    Zobrazí dialog pro výběr názvu (CZ/ENG).
    Po výběru přepne container na akci `search`, aby URL v historii
    odpovídala výsledkovému listu (a po stopu přehrávání se dialog
    znovu nespouštěl).
    """
    
    dialog = xbmcgui.Dialog()
    
    # Ošetření vstupu z URL (zbavíme se bílých znaků)
    cz_title = cz_title.strip()
    eng_title = eng_title.strip()
    year = year.strip()
    cancel_return_url = _normalize_plugin_return_url(cancel_return_url)
    return_after_play_url = _normalize_plugin_return_url(return_after_play_url)
    
    choices = []
    
    # 1. Přidání možnosti CZ názvu (pokud existuje a není shodný s ENG)
    if cz_title and cz_title != eng_title:
        choices.append(f"Hledat (CZ): {cz_title}")
        
    # 2. Přidání možnosti ENG názvu
    choices.append(f"Hledat (ENG): {eng_title}")
    
    selection = dialog.select("Vyberte název pro vyhledávání", choices)
    
    # ----------------------------------------------------
    # Zpracování ZRUŠENÍ (selection == -1)
    # ----------------------------------------------------
    if selection == -1:
        try:
            xbmcgui.Window(10000).clearProperty(_POST_PLAY_RETURN_PROP)
            # Legacy cleanup (post_play_return_url se už nepoužívá)
            addon.setSetting('post_play_return_url', '')
        except Exception:
            pass
        if cancel_return_url:
            safe_url = str(cancel_return_url).replace('"', '%22')
            xbmc.executebuiltin(f'ActivateWindow(Videos,"{safe_url}",return)')
            return

        # Zde už není potřeba endOfDirectory, protože is_folder=False
        return
    
    # ----------------------------------------------------
    # Zpracování ÚSPĚCHU (selection >= 0)
    # ----------------------------------------------------
    
    selected_title = None
    
    # Určení vybraného názvu
    if len(choices) == 2:
        selected_title = cz_title if selection == 0 else eng_title
    else:
        # Máme jen jednu volbu (ENG)
        selected_title = eng_title

    if selected_title:
        final_query = f"{selected_title} {year}".strip()
        log.info(
            f"show_search_dialog: Container.Update search "
            f"q='{final_query}', tmdb_id={tmdb_id}, mediatype={mediatype}"
        )
        
        search_params: Dict[str, Any] = {'action': 'search', 'q': final_query}
        if tmdb_id:
            search_params['tmdb_id'] = tmdb_id
        if mediatype:
            search_params['mediatype'] = mediatype

        if return_after_play_url:
            try:
                action_for_return = _extract_action(return_after_play_url)
                if action_for_return:
                    xbmcgui.Window(10000).setProperty(_POST_PLAY_RETURN_PROP, return_after_play_url)
                    # Legacy fallback pro prostředí, kde service nevidí Window property.
                    addon.setSetting('post_play_return_url', return_after_play_url)
                    log.info(
                        f"show_search_dialog: post-play return ulozen ({action_for_return})"
                    )
                else:
                    xbmcgui.Window(10000).clearProperty(_POST_PLAY_RETURN_PROP)
                    addon.setSetting('post_play_return_url', '')
                    log.warning(
                        "show_search_dialog: return_after_play_url bez action, ignoruji"
                    )
            except Exception:
                pass

        target_url = get_url_fn(**search_params)
        try:
            # Po zavření modal dialogu je potřeba malý odklad, jinak Kodi odmítne
            # změnu containeru ("active modal dialogs").
            safe_target_url = _alarmclock_safe_url(target_url)
            # Odebráno 'replace', aby Container.Update jen pridal novy list nad ten puvodni
            jump_cmd = f'Container.Update({safe_target_url})'
            xbmc.executebuiltin(
                f'AlarmClock(sm3_search_jump,{jump_cmd},00:00:01,silent)'
            )
        except Exception:
            # Fallback: přímé synchronní vykreslení, aby uživatel vždy dostal výsledky
            search(search_params, addon, handle, profile, get_url_fn, api, revalidate, popinfo)
        return

# 🚨 ZMĚNA 5: Přidání tmdb_id a mediatype do signatury
def search(params, addon, handle, profile, get_url, api, revalidate, popinfo,
           categories=None, sorts=None, none_placeholder='%#NONE#%'):
    """
    Kořen vyhledávání (Webshare) + nové hledání + historie.
    Opravuje propisování placeholderu NONE_WHAT (%#NONE#%) do vstupního dialogu.
    """
    # Výchozí hodnoty, pokud nejsou dodány z router bridge (sm3_entry)
    categories = categories or ['', 'video', 'images', 'audio', 'archives', 'docs', 'adult']
    sorts = sorts or ['', 'recent', 'rating', 'largest', 'smallest']

    def _is_placeholder(v: str) -> bool:
        if not isinstance(v, str):
            return False
        v = v.strip()
        return (v == none_placeholder) or ("%#NONE#%" in v)

    def _sanitize_default(v: str) -> str:
        if not v:
            return ""
        return "" if _is_placeholder(v) else v.strip()

    xbmcplugin.setPluginCategory(handle, addon.getAddonInfo('name') + " \\ " + 'Vyhledávání')
    updateListing = False
    token = None
    what = None
    
    # 🚨 ZMĚNA 6: Extrakce tmdb_id a mediatype z params pro předání do dosearch
    tmdb_id = params.get('tmdb_id')
    mediatype = params.get('mediatype')
    log.info(f"search(): Přijaté parametry → tmdb_id={tmdb_id}, mediatype={mediatype}, params={params}")


    # 1) Odstranění položky z historie
    if 'remove' in params:
        removesearch(params['remove'], profile)
        updateListing = True

    # 2) Přidání identu do fronty (původní kompatibilita)
    if 'toqueue' in params:
        # Import zde by opět vedl ke kruhové závislosti; použij zavedenou akci queue_add
        # toqueue(params['toqueue'], token)  # vynecháno – nahrazeno v dosearch kontextovým menu
        updateListing = True

    # 3) Integrace s TMDb/Trakt: ?q=...
    if 'q' in params:
        what = params['q']
        if not _is_placeholder(what) and what.strip():
            storesearch(what.strip(), profile, addon)

    # 4) Dialogové „Nové hledání“
    if 'ask' in params and (what is None):
        query = xbmcgui.Dialog().input(
            heading='Zadejte hledaný výraz',
            defaultt="",
            type=xbmcgui.INPUT_ALPHANUM
        )
        if query:
            what = query.strip()
            if what:
                storesearch(what, profile, addon)
                updateListing = True
        else:
            xbmcplugin.endOfDirectory(handle, updateListing=True)
            return

    # 5) Spuštění hledání
    if what is None and 'what' in params:
        what = params['what']

    if what is not None:
        is_none = _is_placeholder(what)
        # Fallback hodnoty (původně v settings.xml): scategory=1 (video), ssort=0 (recent), slimit=25
        category = params['category'] if 'category' in params else categories[1]
        sort = params['sort'] if 'sort' in params else sorts[0]
        limit = int(params['limit']) if 'limit' in params else 25
        offset = int(params['offset']) if 'offset' in params else 0

        if 'offset' not in params:
            if not is_none and isinstance(what, str) and what.strip():
                updateListing = True
        # 🚨 ZMĚNA 7: Předání tmdb_id a mediatype do dosearch
        log.info(f"search(): Volám dosearch s tmdb_id={tmdb_id}, mediatype={mediatype}")
        dosearch(token, what, category, sort, limit, offset, 'search',
                 addon, handle, get_url, api, revalidate, popinfo,
                 none_placeholder=none_placeholder,
                 tmdb_id=tmdb_id,
                 mediatype=mediatype
                 )
        return

    # 6) Kořenové položky
    history = loadsearch(profile)

    li = xbmcgui.ListItem(label='Nové hledání')
    li.setArt({'icon': 'DefaultAddSource.png'})
    xbmcplugin.addDirectoryItem(handle, get_url(action='search', ask=1), li, True)

    li = xbmcgui.ListItem(label='Nejnovější na Webshare')
    li.setArt({'icon': 'DefaultAddonsRecentlyUpdated.png'})
    xbmcplugin.addDirectoryItem(handle, get_url(action='search', what=none_placeholder, sort=sorts[1]), li, True)

    li = xbmcgui.ListItem(label='Největší na Webshare')
    li.setArt({'icon': 'DefaultHardDisk.png'})
    xbmcplugin.addDirectoryItem(handle, get_url(action='search', what=none_placeholder, sort=sorts[3]), li, True)

    for search_text in history:
        safe_default = _sanitize_default(search_text)
        li = xbmcgui.ListItem(label=search_text)
        li.setArt({'icon': 'DefaultAddonsSearch.png'})
        from resources.lib.utils.context_builder import build_context_menu
        item_data = {'search_query': search_text}
        commands = build_context_menu(get_url, item_data, contexts=['search_history_remove'])
        if commands:
            li.addContextMenuItems(commands, replaceItems=True)
        xbmcplugin.addDirectoryItem(handle, get_url(action='search', what=safe_default), li, True)

    xbmcplugin.endOfDirectory(handle, updateListing=updateListing)


def webshare_detect_cz(params, addon, handle, api, revalidate, popinfo):
    """
    Spustí ffprobe pro jeden konkrétní Webshare stream a zobrazí formátovaný
    report (Video, Audio stopy, Titulky).
    """
    import xbmcgui
    import xbmcplugin
    from resources.lib.series.subs_probe import _get_stream_url, _probe_with_ffprobe
    from resources.lib.series.probe_helpers import parse_ffprobe_streams

    ident = params.get('ident')
    name = params.get('name', 'Stream')

    if not ident:
        popinfo("Nelze detekovat: chybí ident streamu", icon=xbmcgui.NOTIFICATION_WARNING)
        xbmcplugin.endOfDirectory(handle, succeeded=False)
        return

    token = revalidate()
    duuid = addon.getSetting('duuid')

    progress = xbmcgui.DialogProgress()
    progress.create("Detekce CZ (FFprobe)", f"Zjišťuji link pro:\n{name}...")

    # Získáme přímý video link z Webshare
    url = _get_stream_url(api, token, ident, duuid)
    if not url:
        progress.close()
        popinfo("Nelze detekovat: file_link nenalezen", icon=xbmcgui.NOTIFICATION_WARNING)
        xbmcplugin.endOfDirectory(handle, succeeded=False)
        return

    progress.update(50, "Analyzuji stream přes FFprobe...\nTo může trvat několik sekund.")

    # Analyzujeme stream na pozadí pomocí FFprobe
    ffjson, langs = _probe_with_ffprobe(url)
    progress.update(90, "Formátuji výsledky detekce...")
    
    # Přetvoření raw JSONU do našeho standardizovaného dictu
    meta = parse_ffprobe_streams(ffjson)
    
    progress.close()

    if not ffjson.get('streams'):
        xbmcgui.Dialog().ok("Detekce CZ", "Nebyly nalezeny žádné streamy nebo FFprobe selhal.\nUjistěte se, že máte FFprobe správně nakonfigurován.")
        xbmcplugin.endOfDirectory(handle, succeeded=False)
        return

    # --- Sestavení textového výstupu pro Dialog ---
    lines = []
    lines.append(f"====== DETEKCE PRO STREAME ======")
    lines.append(f"{name}\n")
    
    # Video report
    vid = meta.get("video", {})
    w, h = vid.get("width", 0), vid.get("height", 0)
    lines.append(f"VIDEO: {w}x{h} ({vid.get('resolution_tag', 'N/A')})")
    if vid.get("hdr") or vid.get("dv"):
        lines.append(f"  > HDR: {'Ano' if vid.get('hdr') else 'Ne'} | Dolby Vision: {'Ano' if vid.get('dv') else 'Ne'}")
    lines.append("")

    # Audio report
    lines.append("AUDIO STOPY:")
    audio = meta.get("audio_tracks", [])
    if not audio:
        lines.append("  Žádné audiostopy (nebo se je nepovedlo načíst).")
    else:
        for i, a in enumerate(audio, 1):
            lang = (a.get("lang") or "und").upper()
            ch = a.get("channels", "?")
            codec = (a.get("codec") or "?").upper()
            title = a.get("title", "")
            
            # Heuristika pro výrazný štítek české audio stopy
            cz_flag = " ⭐ [CZdab]" if lang in ("CS", "CZ", "CZE") or "CZ" in title.upper() else ""
            lines.append(f"  {i}) {lang} | Kanály: {ch} | Kodek: {codec} | Název: {title}{cz_flag}")
    lines.append("")

    # Titulkový report
    lines.append("TITULKY:")
    subs = meta.get("subs_langs", [])
    if not subs:
        lines.append("  Žádné vestavěné titulky.")
    else:
        subs_text = ", ".join(s.upper() for s in subs)
        lines.append(f"  Nalezené cizí/lokální jazyky:\n  {subs_text}")
        if meta.get("cz_subs"):
            lines.append("  ⭐ Nalezeny CZ/SK titulky!")

    # Modální výpis (stejné jako zobrazení popisu)
    xbmcgui.Dialog().textviewer("Výsledek detekce (FFprobe)", "\n".join(lines))
    xbmcplugin.endOfDirectory(handle, succeeded=False)