# wcs/csfd_handler.py
from wcs.skin import context as menu_context

import requests
import re
import xbmc
import xbmcplugin
import xbmcgui
from urllib.parse import quote_plus
import time
import hashlib
import json

from wcs.ui import UI as ui
from wcs import user_data, utils
from . import TMDbCache as tmdb_cache, TMDbClient as tmdb_handler


def get_csfd_top_movies(page=1, addon=None):
    """
    Získá nejlepší filmy z ČSFD žebříčku s cacheováním a optimalizací.
    
    Args:
        page (int): Číslo stránky (1-50, závisí na nastavení items_per_page)
        addon: Instance addonu pro získání nastavení
        
    Returns:
        list: Seznam slovníků s daty filmů z ČSFD
    """
    # Získání cache nastavení z konfigurace
    if addon:
        cache_hours = int(addon.getSetting('csfd_cache_hours') or 24)
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        cache_hours = 24
        items_per_page = 20
    
    # Optimalizace: Pokud je items_per_page menší než 100, načteme jen potřebné filmy
    # ČSFD má 1000 nejlepších filmů, takže při 20 na stránku máme 50 stránek
    if items_per_page < 100:
        # Výpočet rozsahu filmů pro tuto stránku
        start_rank = (page - 1) * items_per_page + 1
        end_rank = page * items_per_page
        
        # Najdeme, které ČSFD stránky potřebujeme načíst
        # ČSFD má 100 filmů na stránku, takže potřebujeme načíst více stránek
        csfd_start_page = ((start_rank - 1) // 100) + 1
        csfd_end_page = ((end_rank - 1) // 100) + 1
        
        all_movies = []
        
        # Načteme všechny potřebné ČSFD stránky
        for csfd_page in range(csfd_start_page, csfd_end_page + 1):
            csfd_movies = _fetch_csfd_page(csfd_page, addon, cache_hours)
            if csfd_movies:
                all_movies.extend(csfd_movies)
        
        # Vybereme jen filmy pro aktuální stránku
        start_index = (start_rank - 1) % 100
        if csfd_start_page == csfd_end_page:
            # Všechny filmy jsou na jedné ČSFD stránce
            return all_movies[start_index:start_index + items_per_page]
        else:
            # Filmy jsou na více ČSFD stránkách
            result = []
            current_index = start_index
            
            for csfd_page in range(csfd_start_page, csfd_end_page + 1):
                csfd_movies = _fetch_csfd_page(csfd_page, addon, cache_hours)
                if not csfd_movies:
                    continue
                
                if csfd_page == csfd_start_page:
                    # První stránka - začínáme od start_index
                    result.extend(csfd_movies[current_index:])
                elif csfd_page == csfd_end_page:
                    # Poslední stránka - končíme na end_index
                    end_index = (end_rank - 1) % 100 + 1
                    result.extend(csfd_movies[:end_index])
                else:
                    # Střední stránky - bereme všechny
                    result.extend(csfd_movies)
                
                if len(result) >= items_per_page:
                    break
            
            return result[:items_per_page]
    else:
        # Standardní režim - načteme celou ČSFD stránku
        return _fetch_csfd_page(page, addon, cache_hours)


def _fetch_csfd_page(page, addon, cache_hours):
    """
    Pomocná funkce pro načtení jedné ČSFD stránky s cacheováním.
    
    Args:
        page (int): Číslo ČSFD stránky (1-10)
        addon: Instance addonu
        cache_hours (int): Cache doba v hodinách
        
    Returns:
        list: Seznam filmů z ČSFD stránky
    """
    # Výpočet from parametru (ČSFD používá from=1, from=101, from=201, atd.)
    from_param = (page - 1) * 100 + 1
    url = f"https://www.csfd.cz/zebricky/filmy/nejlepsi/?from={from_param}"
    
    # Cache endpoint a parametry
    endpoint = f"/csfd/top_movies/page_{page}"
    params = {}
    
    def fetch_csfd_data():
        """Funkce pro stažení dat z ČSFD"""
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji stránku {page} z ČSFD žebříčku", xbmc.LOGINFO)
            
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
            }
            
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            
            return _parse_chart_response(response.text, url)
            
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování ČSFD dat: {e}", xbmc.LOGERROR)
            return []
    
    # Použití cache s optimalizovanou logikou
    movies = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_data, expire_seconds=cache_hours * 3600)
    return movies if movies else []


_TMDB_CHART_QUERY = {
    'nejlepsi': ('top_rated', {}),
    'nejoblibenejsi': ('popular', {}),
    'nejrozporuplnejsi': ('discover', {'sort_by': 'vote_count.desc', 'vote_average.lte': '6.5', 'vote_average.gte': '5.0', 'vote_count.gte': '2000'}),
    'nejhorsi': ('discover', {'sort_by': 'vote_average.asc', 'vote_count.gte': '1500'}),
}


def _is_bot_wall(html):
    """ČSFD je za ochranou proti botům (Anubis); místo žebříčku vrací výzvu."""
    return 'anubis' in html[:6000].lower() or "not a bot" in html[:2000].lower()


def _parse_chart_response(html, url):
    """Naparsuje ČSFD žebříček; při bot-wallu doplní stejný žebříček z TMDb."""
    if not _is_bot_wall(html):
        return parse_csfd_movies_html(html)
    m = re.search(r'/zebricky/(filmy|serialy)/([a-z]+)/\?from=(\d+)', url)
    if not m:
        return []
    xbmc.log("[WCS ČSFD] ČSFD blokuje boty (Anubis), používám TMDb žebříček", xbmc.LOGINFO)
    return _tmdb_chart_fallback(m.group(1), m.group(2), (int(m.group(3)) - 1) // 20 + 1)


def _tmdb_chart_fallback(media, kind, first_page):
    """Vrátí 100 položek (5 TMDb stránek) ve formátu ČSFD parseru."""
    mode, extra = _TMDB_CHART_QUERY.get(kind, _TMDB_CHART_QUERY['nejlepsi'])
    is_movie = media == 'filmy'
    kind_path = 'movie' if is_movie else 'tv'
    try:
        api_key = tmdb_handler.get_tmdb_api_key()
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] TMDb fallback bez klíče: {e}", xbmc.LOGERROR)
        return []
    endpoint = f"https://api.themoviedb.org/3/{kind_path}/{mode if mode != 'discover' else 'discover/' + kind_path}"
    if mode == 'discover':
        endpoint = f"https://api.themoviedb.org/3/discover/{kind_path}"
    items = []
    for page in range(first_page, first_page + 5):
        try:
            params = {'api_key': api_key, 'language': 'cs-CZ', 'page': page}
            params.update(extra)
            r = requests.get(endpoint, params=params, timeout=10)
            r.raise_for_status()
            results = r.json().get('results', [])
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] TMDb fallback chyba: {e}", xbmc.LOGERROR)
            break
        for it in results:
            title = it.get('title') if is_movie else it.get('name')
            date = it.get('release_date') if is_movie else it.get('first_air_date')
            if not title:
                continue
            items.append({
                'csfd_title': title,
                'csfd_year': (date or '')[:4],
                'csfd_rating': str(int(round((it.get('vote_average') or 0) * 10))),
                'csfd_rating_count': str(it.get('vote_count') or ''),
                'csfd_genres': '', 'csfd_countries': '', 'csfd_director': '',
                'csfd_actors': '', 'csfd_rank': '',
                'csfd_url': '',
            })
    return items



def parse_csfd_movies_html(html):
    """
    Parsuje HTML stránku ČSFD žebříčku a extrahuje data filmů.
    
    Args:
        html (str): HTML obsah stránky
        
    Returns:
        list: Seznam slovníků s daty filmů
    """
    movies = []
    
    try:
        # Nejdříve zkusíme najít tabulkové řádky s filmy
        # ČSFD používá různé struktury, zkusíme několik pattern
        
        # Pattern 1: Tabulkové řádky s třídou obsahující "film"
        film_rows = re.findall(r'<tr[^>]*class="[^"]*film[^"]*"[^>]*>(.*?)</tr>', html, re.DOTALL | re.IGNORECASE)
        
        if not film_rows:
            # Pattern 2: Divs s třídou obsahující "film"
            film_rows = re.findall(r'<div[^>]*class="[^"]*film[^"]*"[^>]*>(.*?)</div>', html, re.DOTALL | re.IGNORECASE)
        
        if not film_rows:
            # Pattern 3: Obecné odkazy na filmy
            film_rows = re.findall(r'<a[^>]*href="/film/[^"]*"[^>]*>.*?</a>.*?(?=<a[^>]*href="/film/|$)', html, re.DOTALL)
        
        if not film_rows:
            # Pattern 4: Fallback - hledáme jakékoliv odkazy na /film/
            film_links = re.findall(r'<a[^>]*href="(/film/[^"]*)"[^>]*>(.*?)</a>', html, re.DOTALL | re.IGNORECASE)
            for link, title in film_links:
                try:
                    # Vytvoříme základní strukturu filmu
                    movie_data = {
                        'csfd_title': re.sub(r'<[^>]+>', '', title).strip(),
                        'csfd_url': f"https://www.csfd.cz{link}",
                        'csfd_year': '',
                        'csfd_rating': '',
                        'csfd_rating_count': '',
                        'csfd_genres': '',
                        'csfd_countries': '',
                        'csfd_director': '',
                        'csfd_actors': '',
                        'csfd_rank': ''
                    }
                    
                    # Pokusíme se najít rok v okolním kontextu
                    context_start = max(0, html.find(link) - 500)
                    context_end = min(len(html), html.find(link) + 500)
                    context = html[context_start:context_end]
                    
                    year_match = re.search(r'\((\d{4})\)', context)
                    if year_match:
                        movie_data['csfd_year'] = year_match.group(1)
                    
                    if movie_data['csfd_title']:
                        movies.append(movie_data)
                        
                except Exception as e:
                    xbmc.log(f"[WCS ČSFD] Chyba při fallback parsování: {e}", xbmc.LOGDEBUG)
                    continue
        else:
            # Standardní parsování nalezených řádků
            for row in film_rows:
                try:
                    movie_data = parse_single_csfd_movie_regex(row)
                    if movie_data:
                        movies.append(movie_data)
                except Exception as e:
                    xbmc.log(f"[WCS ČSFD] Chyba při parsování řádku filmu: {e}", xbmc.LOGDEBUG)
                    continue
        
        xbmc.log(f"[WCS ČSFD] Úspěšně naparsováno {len(movies)} filmů", xbmc.LOGINFO)
        
        # Pokud nemáme žádné filmy, zkusíme debugovací výpis
        if not movies:
            xbmc.log(f"[WCS ČSFD] DEBUG: Nenalezeny žádné filmy, HTML začátek: {html[:500]}", xbmc.LOGINFO)
        
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při parsování HTML: {e}", xbmc.LOGERROR)
    
    return movies


def parse_single_csfd_movie_regex(html_content):
    """
    Parsuje data jednoho filmu z HTML obsahu pomocí regex.
    
    Args:
        html_content (str): HTML obsahující informace o filmu
        
    Returns:
        dict: Data filmu nebo None pokud se nepodařilo parsovat
    """
    try:
        movie_data = {
            'csfd_title': '',
            'csfd_year': '',
            'csfd_director': '',
            'csfd_actors': '',
            'csfd_rating': '',
            'csfd_rating_count': '',
            'csfd_genres': '',
            'csfd_countries': '',
            'csfd_url': '',
            'csfd_rank': ''
        }
        
        # Odstranění HTML tagů pro získání čistého textu
        clean_text = re.sub(r'<[^>]+>', ' ', html_content)
        clean_text = re.sub(r'\s+', ' ', clean_text).strip()
        
        # Hledání odkazu na film a názvu
        link_match = re.search(r'<a[^>]*href="([^"]*)"[^>]*>(.*?)</a>', html_content, re.DOTALL | re.IGNORECASE)
        if link_match:
            href = link_match.group(1)
            title_html = link_match.group(2)
            
            # Vyčištění názvu od HTML tagů
            movie_data['csfd_title'] = re.sub(r'<[^>]+>', '', title_html).strip()
            
            # URL filmu
            if href and not href.startswith('http'):
                movie_data['csfd_url'] = f"https://www.csfd.cz{href}"
            else:
                movie_data['csfd_url'] = href
        
        # Hledání roku v závorce
        year_match = re.search(r'\((\d{4})\)', clean_text)
        if year_match:
            movie_data['csfd_year'] = year_match.group(1)
        
        # Hledání hodnocení (procenta)
        rating_match = re.search(r'(\d+[,.]?\d*)\s*%', clean_text)
        if rating_match:
            movie_data['csfd_rating'] = rating_match.group(1).replace(',', '.')
        
        # Hledání počtu hodnocení
        rating_count_match = re.search(r'(\d+(?:\s+\d+)*)\s+hodnocení', clean_text)
        if rating_count_match:
            movie_data['csfd_rating_count'] = rating_count_match.group(1).replace(' ', '')
        
        # Hledání žánrů (obvykle oddělené lomítky)
        genre_match = re.search(r'([A-Za-z]+(?:\s*/\s*[A-Za-z]+)+)', clean_text)
        if genre_match:
            movie_data['csfd_genres'] = genre_match.group(1)
        
        # Hledání zemí (obvykle jsou za žánry nebo v závorkách)
        country_match = re.search(r'([A-Z][a-z]+(?:\s*/\s*[A-Z][a-z]+)*),?\s*\d{4}', clean_text)
        if country_match:
            movie_data['csfd_countries'] = country_match.group(1)
        
        # Kontrola, zda máme alespoň název
        if movie_data['csfd_title']:
            return movie_data
        
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při parsování jednotlivého filmu: {e}", xbmc.LOGDEBUG)
    
    return None


def parse_single_csfd_movie(element):
    """
    Parsuje data jednoho filmu z ČSFD elementu - wrapper pro regex verzi.
    
    Args:
        element: HTML řetězec obsahující informace o filmu
        
    Returns:
        dict: Data filmu nebo None pokud se nepodařilo parsovat
    """
    return parse_single_csfd_movie_regex(str(element))


def parse_single_csfd_movie_row(row_element):
    """
    Parsuje data filmu z řádku tabulky ČSFD - wrapper pro regex verzi.
    
    Args:
        row_element: HTML řetězec řádku tabulky
        
    Returns:
        dict: Data filmu nebo None pokud se nepodařilo parsovat
    """
    return parse_single_csfd_movie_regex(str(row_element))


def match_csfd_to_tmdb(csfd_title, csfd_year, addon=None):
    """
    Pokusí se spárovat ČSFD film s TMDb pro získání metadat s cachováním.
    
    Args:
        csfd_title (str): Název filmu z ČSFD
        csfd_year (str): Rok filmu z ČSFD
        addon: Instance addonu
        
    Returns:
        dict: TMDb data filmu nebo None pokud nenalezeno
    """
    if not csfd_title:
        return None
    
    # Získání cache nastavení z konfigurace
    if addon:
        cache_days = int(addon.getSetting('csfd_tmdb_cache_days') or 7)
    else:
        cache_days = 7
    
    # Cache endpoint pro TMDb vyhledávání
    endpoint = f"/tmdb/search_movie"
    clean_title = clean_title_for_search(csfd_title)
    params = {
        'query': clean_title,
        'year': csfd_year if csfd_year else ''
    }
    
    def fetch_tmdb_data():
        """Funkce pro stažení dat z TMDb"""
        try:
            # Získání TMDb API klíče podle paměti - pokud chybí, zobrazí dialog
            if addon:
                api_key = tmdb_handler.get_tmdb_api_key(addon)
            else:
                api_key = tmdb_handler.get_tmdb_api_key()
            
            # Vyhledávání v TMDb
            search_url = 'https://api.themoviedb.org/3/search/movie'
            api_params = {
                'api_key': api_key,
                'language': 'cs-CZ',
                'query': clean_title
            }
            
            if csfd_year:
                api_params['year'] = csfd_year
            
            response = requests.get(search_url, params=api_params, timeout=10)
            response.raise_for_status()
            results = response.json().get('results', [])
            
            if not results:
                # Zkusíme hledat bez roku
                if 'year' in api_params:
                    del api_params['year']
                    response = requests.get(search_url, params=api_params, timeout=10)
                    response.raise_for_status()
                    results = response.json().get('results', [])
            
            if results:
                # Najdeme nejlepší shodu
                best_match = find_best_tmdb_match(results, csfd_title, csfd_year)
                return best_match
            
            return None
            
        except ValueError as e:
            # TMDb API klíč není nastaven nebo je neplatný - dialog už se zobrazil
            xbmc.log(f"[WCS ČSFD] TMDb API klíč problém: {e}", xbmc.LOGDEBUG)
            return None
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 401:
                # Neplatný API klíč - dialog už se zobrazil při get_tmdb_api_key()
                xbmc.log(f"[WCS ČSFD] TMDb API neplatný klíč", xbmc.LOGDEBUG)
                return None
            else:
                xbmc.log(f"[WCS ČSFD] TMDb HTTP chyba při párování: {csfd_title} - {e}", xbmc.LOGDEBUG)
                return None
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při párování s TMDb: {csfd_title} - {e}", xbmc.LOGDEBUG)
            return None
    
    # Použití cache pro TMDb vyhledávání s konfigurovatelnou dobou
    tmdb_data = tmdb_cache.get_or_fetch(endpoint, params, fetch_tmdb_data, expire_seconds=cache_days * 24 * 3600)
    return tmdb_data


def clean_title_for_search(title):
    """
    Vyčistí název filmu pro lepší vyhledávání v TMDb.
    
    Args:
        title (str): Původní název
        
    Returns:
        str: Vyčištěný název
    """
    if not title:
        return ''
    
    # Odstranění českých přepisů a speciálních znaků
    clean = title.strip()
    
    # Odstranění poznámek v závorkách na konci
    clean = re.sub(r'\s*\([^)]*\)\s*$', '', clean)
    
    # Odstranění prefixů jako "Film:" apod.
    clean = re.sub(r'^[^:]+:\s*', '', clean)
    
    return clean.strip()


def find_best_tmdb_match(tmdb_results, csfd_title, csfd_year):
    """
    Najde nejlepší shodu mezi TMDb výsledky.
    
    Args:
        tmdb_results (list): Seznam výsledků z TMDb
        csfd_title (str): Původní název z ČSFD
        csfd_year (str): Rok z ČSFD
        
    Returns:
        dict: Nejlepší TMDb shoda
    """
    if not tmdb_results:
        return None
    
    # Pokud máme rok, preferujeme filmy se stejným rokem
    if csfd_year:
        year_matches = [
            movie for movie in tmdb_results 
            if movie.get('release_date', '').startswith(csfd_year)
        ]
        if year_matches:
            return year_matches[0]
    
    # Jinak vrátíme první výsledek (nejrelevantnější podle TMDb)
    return tmdb_results[0]


def list_csfd_movies(params, addon, handle):
    """
    Zobrazí seznam filmů z ČSFD žebříčku v Kodi.
    
    Args:
        params (dict): Parametry požadavku
        addon: Instance addonu
        handle: Handle pro Kodi plugin
    """
    page = int(params.get('page', 1))
    
    # Získání nastavení pro počet položek na stránku
    if addon:
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        items_per_page = 20
    
    xbmcplugin.setPluginCategory(handle, f'ČSFD / Nejlepší filmy - Stránka {page}')
    xbmcplugin.setContent(handle, 'movies')
    
    try:
        # Získání filmů z ČSFD
        csfd_movies = get_csfd_top_movies(page, addon)
        
        if not csfd_movies:
            ui.popinfo(addon.getLocalizedString(30502), addon.getAddonInfo('name'))
            xbmcplugin.endOfDirectory(handle)
            return
        
        # Zobrazení filmů s správným počítáním ranků
        start_rank = (page - 1) * items_per_page + 1
        for i, csfd_movie in enumerate(csfd_movies):
            try:
                create_csfd_movie_listitem(csfd_movie, addon, handle, start_rank + i)
            except Exception as e:
                xbmc.log(f"[WCS ČSFD] Chyba při vytváření položky pro film: {csfd_movie.get('csfd_title', 'Unknown')} - {e}", xbmc.LOGDEBUG)
                continue
        
        # Přidání navigačních tlačítek
        add_csfd_navigation(page, handle, addon)
        
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při zobrazování ČSFD filmů: {e}", xbmc.LOGERROR)
        ui.popinfo(addon.getLocalizedString(30503).replace('%s', str(e)), addon.getAddonInfo('name'))
    
    xbmcplugin.endOfDirectory(handle)


def create_csfd_movie_listitem(csfd_movie, addon, handle, rank=None):
    """
    Vytvoří Kodi ListItem pro ČSFD film.
    
    Args:
        csfd_movie (dict): Data filmu z ČSFD
        addon: Instance addonu
        handle: Handle pro Kodi plugin
        rank (int): Pořadí filmu v žebříčku
    """
    csfd_title = csfd_movie.get('csfd_title', 'Neznámý film')
    csfd_year = csfd_movie.get('csfd_year', '')
    csfd_rating = csfd_movie.get('csfd_rating', '')
    
    # Kontrola dostupnosti TMDb API klíče před pokusem o párování
    tmdb_data = None
    try:
        # Pouze zkusíme získat API klíč, pokud se podaří, provedeme párování
        tmdb_handler.get_tmdb_api_key(addon)
        # Pokus o získání TMDb dat - pouze pro zobrazené filmy
        tmdb_data = match_csfd_to_tmdb(csfd_title, csfd_year, addon)
    except ValueError:
        # TMDb API klíč není nastaven - použijeme pouze ČSFD data
        tmdb_data = None
    except Exception:
        # Jiná chyba při párování - také použijeme pouze ČSFD data
        tmdb_data = None
    
    # Sestavení labelu
    if rank:
        label = f"{rank}. {csfd_title}"
    else:
        label = csfd_title
    
    if csfd_year:
        label += f" ({csfd_year})"
    
    if csfd_rating:
        label += f" - {csfd_rating}%"
    
    # Vytvoření ListItem
    listitem = xbmcgui.ListItem(label=label)
    
    # Nastavení metadat
    info = {
        'title': csfd_title,
        'year': int(csfd_year) if csfd_year else 0,
        'mediatype': 'movie'
    }
    
    # Přidání TMDb metadat pokud jsou dostupná
    if tmdb_data:
        if tmdb_data.get('overview'):
            info['plot'] = tmdb_data['overview']
        if tmdb_data.get('vote_average'):
            info['rating'] = float(tmdb_data['vote_average'])
        if tmdb_data.get('genre_ids'):
            # Můžeme přidat žánry později když budeme mít mapping
            pass
        
        # Poster z TMDb
        poster_path = tmdb_data.get('poster_path')
        if poster_path:
            poster_url = f"https://image.tmdb.org/t/p/w500{poster_path}"
            listitem.setArt({'thumb': poster_url, 'poster': poster_url})
    
    # Pokud nemáme TMDb data, použijeme ČSFD informace
    if not tmdb_data:
        # Sestavení popisu z dostupných ČSFD dat
        plot_parts = []
        if csfd_movie.get('csfd_genres'):
            plot_parts.append(f"Žánry: {csfd_movie['csfd_genres']}")
        if csfd_movie.get('csfd_countries'):
            plot_parts.append(f"Země: {csfd_movie['csfd_countries']}")
        if csfd_rating and csfd_movie.get('csfd_rating_count'):
            plot_parts.append(f"Hodnocení ČSFD: {csfd_rating}% ({csfd_movie['csfd_rating_count']} hodnocení)")
        
        if plot_parts:
            info['plot'] = '\n'.join(plot_parts)
    
    utils.set_video_info_tag(listitem, info)
    
    # Kontextové menu - pouze pokud máme TMDb data
    if tmdb_data and tmdb_data.get('id'):
        from wcs.ui.ContextMenu import create_movie_context_menu
        commands = create_movie_context_menu(
            addon=addon,
            tmdb_id=tmdb_data['id'],
            title=csfd_title,
            year=csfd_year,
            plot=info.get('plot', ''),
            poster=f"https://image.tmdb.org/t/p/w500{tmdb_data.get('poster_path')}" if tmdb_data.get('poster_path') else ''
        )
        menu_context.add_legacy(listitem, commands)
    else:
        # Kontextové menu pouze s ČSFD odkazy
        csfd_url = csfd_movie.get('csfd_url', '')
        if csfd_url:
            commands = [
                ("Otevřít na ČSFD", f"RunPlugin(plugin://{addon.getAddonInfo('id')}?action=open_csfd_url&url={quote_plus(csfd_url)})")
            ]
            menu_context.add_legacy(listitem, commands)
    
    # URL pro zobrazení detailů nebo vyhledávání
    if tmdb_data and tmdb_data.get('id'):
        # Máme TMDb data - použijeme standardní detailní zobrazení
        url = f"plugin://{addon.getAddonInfo('id')}?action=show_wcs_details&media_type=movie&tmdb_id={tmdb_data['id']}"
    else:
        # Nemáme TMDb data - přesměrujeme na vyhledávání
        search_query = f"{csfd_title} {csfd_year}".strip()
        url = f"plugin://{addon.getAddonInfo('id')}?action=search&what={quote_plus(search_query)}&handle={handle}"
    
    xbmcplugin.addDirectoryItem(handle, url, listitem, False)


def add_csfd_navigation(current_page, handle, addon):
    """
    Přidá navigační tlačítka pro stránkování ČSFD žebříčku.
    
    Args:
        current_page (int): Aktuální stránka
        handle: Handle pro Kodi plugin
        addon: Instance addonu
    """
    # Získání nastavení pro počet položek na stránku
    if addon:
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        items_per_page = 20
    
    # ČSFD má cca 1000 nejlepších filmů
    total_movies = 1000
    max_page = (total_movies + items_per_page - 1) // items_per_page
    
    # Předchozí stránka
    if current_page > 1:
        prev_item = xbmcgui.ListItem(label=addon.getLocalizedString(30505).replace('%d', str(current_page - 1)))
        prev_item.setArt({'icon': 'DefaultFolderBack.png'})
        prev_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_top_movies&page={current_page - 1}"
        xbmcplugin.addDirectoryItem(handle, prev_url, prev_item, True)
    
    # Následující stránka
    if current_page < max_page:
        next_item = xbmcgui.ListItem(label=addon.getLocalizedString(30506).replace('%d', str(current_page + 1)))
        next_item.setArt({'icon': 'DefaultFolder.png'})
        next_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_top_movies&page={current_page + 1}"
        xbmcplugin.addDirectoryItem(handle, next_url, next_item, True)


def open_csfd_url(params, addon):
    """
    Otevře ČSFD URL v prohlížeči.
    
    Args:
        params (dict): Parametry obsahující URL
        addon: Instance addonu
    """
    url = params.get('url', '')
    if url:
        import subprocess
        import platform
        
        try:
            if platform.system() == "Windows":
                subprocess.run(['start', url], shell=True)
            elif platform.system() == "Darwin":  # macOS
                subprocess.run(['open', url])
            else:  # Linux
                subprocess.run(['xdg-open', url])
        except Exception:
            # Fallback - zkopírování URL do schránky
            ui.popinfo(f"URL zkopírováno: {url}", addon.getAddonInfo('name'))


def clear_csfd_cache():
    """
    Vymaže cache pro ČSFD žebříčky (nejlepší, nejoblíbenější, nejrozporuplnější, nejhorší; filmy i seriály).
    """
    try:
        removed = 0
        for kind in ('top', 'favorite', 'controversial', 'worst'):
            for media in ('movies', 'series'):
                for page in range(1, 11):
                    removed += tmdb_cache.delete(f"/csfd/{kind}_{media}/page_{page}", {})
        return removed
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při mazání ČSFD cache: {e}", xbmc.LOGERROR)
        return 0


def clear_csfd_tmdb_cache():
    """
    Vymaže TMDb cache pouze pro párování ČSFD (filmy i seriály).
    """
    def is_tmdb_match(data):
        return (isinstance(data, dict) and 'id' in data and 'overview' in data and 'vote_average' in data
                and 'poster_path' in data and ('name' in data or 'title' in data))
    try:
        return tmdb_cache.delete_where(is_tmdb_match)
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při mazání TMDb cache pro ČSFD: {e}", xbmc.LOGERROR)
        return 0


def reset_csfd_cache(params, addon):
    """
    Handler pro reset ČSFD cache z nastavení.
    """
    try:
        cleared_count = clear_csfd_cache()
        ui.popinfo(f"ČSFD cache vymazána. Počet: {cleared_count}", addon.getAddonInfo('name'))
    except Exception as e:
        ui.popinfo(f"Chyba při mazání ČSFD cache: {e}", addon.getAddonInfo('name'))


def reset_csfd_tmdb_cache(params, addon):
    """
    Handler pro reset TMDb cache pro ČSFD z nastavení.
    """
    try:
        cleared_count = clear_csfd_tmdb_cache()
        ui.popinfo(f"TMDb cache pro ČSFD vymazána. Počet: {cleared_count}", addon.getAddonInfo('name'))
    except Exception as e:
        ui.popinfo(f"Chyba při mazání TMDb cache pro ČSFD: {e}", addon.getAddonInfo('name'))


# --- ČSFD SERIÁLY ---

def get_csfd_top_series(page=1, addon=None):
    """
    Získá nejlepší seriály z ČSFD žebříčku s cacheováním a optimalizací.
    """
    if addon:
        cache_hours = int(addon.getSetting('csfd_cache_hours') or 24)
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        cache_hours = 24
        items_per_page = 20
    # Výpočet rozsahu seriálů pro tuto stránku
    start_rank = (page - 1) * items_per_page + 1
    end_rank = page * items_per_page
    csfd_start_page = ((start_rank - 1) // 100) + 1
    csfd_end_page = ((end_rank - 1) // 100) + 1
    all_series = []
    for csfd_page in range(csfd_start_page, csfd_end_page + 1):
        csfd_series = _fetch_csfd_series_page(csfd_page, addon, cache_hours)
        if csfd_series:
            all_series.extend(csfd_series)
    start_index = (start_rank - 1) % 100
    if csfd_start_page == csfd_end_page:
        return all_series[start_index:start_index + items_per_page]
    else:
        result = []
        current_index = start_index
        for csfd_page in range(csfd_start_page, csfd_end_page + 1):
            csfd_series = _fetch_csfd_series_page(csfd_page, addon, cache_hours)
            if not csfd_series:
                continue
            if csfd_page == csfd_start_page:
                result.extend(csfd_series[current_index:])
            elif csfd_page == csfd_end_page:
                end_index = (end_rank - 1) % 100 + 1
                result.extend(csfd_series[:end_index])
            else:
                result.extend(csfd_series)
            if len(result) >= items_per_page:
                break
        return result[:items_per_page]

def _fetch_csfd_series_page(page, addon, cache_hours):
    from_param = (page - 1) * 100 + 1
    url = f"https://www.csfd.cz/zebricky/serialy/nejlepsi/?from={from_param}"
    endpoint = f"/csfd/top_series/page_{page}"
    params = {}
    def fetch_csfd_data():
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji stránku {page} z ČSFD žebříčku seriálů", xbmc.LOGINFO)
            headers = {'User-Agent': 'Mozilla/5.0'}
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            return _parse_chart_response(response.text, url)  # stejný parser funguje i pro seriály
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování ČSFD seriálů: {e}", xbmc.LOGERROR)
            return []
    series = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_data, expire_seconds=cache_hours * 3600)
    return series if series else []

def match_csfd_series_to_tmdb(csfd_title, csfd_year, addon=None):
    if not csfd_title:
        return None
    if addon:
        cache_days = int(addon.getSetting('csfd_tmdb_cache_days') or 7)
    else:
        cache_days = 7
    endpoint = f"/tmdb/search_tv"
    clean_title = clean_title_for_search(csfd_title)
    params = {'query': clean_title, 'year': csfd_year if csfd_year else ''}
    def fetch_tmdb_data():
        try:
            if addon:
                api_key = tmdb_handler.get_tmdb_api_key(addon)
            else:
                api_key = tmdb_handler.get_tmdb_api_key()
            search_url = 'https://api.themoviedb.org/3/search/tv'
            api_params = {'api_key': api_key, 'language': 'cs-CZ', 'query': clean_title}
            if csfd_year:
                api_params['first_air_date_year'] = csfd_year
            response = requests.get(search_url, params=api_params, timeout=10)
            response.raise_for_status()
            results = response.json().get('results', [])
            if not results and 'first_air_date_year' in api_params:
                del api_params['first_air_date_year']
                response = requests.get(search_url, params=api_params, timeout=10)
                response.raise_for_status()
                results = response.json().get('results', [])
            if results:
                return find_best_tmdb_match(results, csfd_title, csfd_year)
            return None
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při párování seriálu s TMDb: {csfd_title} - {e}", xbmc.LOGDEBUG)
            return None
    tmdb_data = tmdb_cache.get_or_fetch(endpoint, params, fetch_tmdb_data, expire_seconds=cache_days * 24 * 3600)
    return tmdb_data

def list_csfd_series(params, addon, handle):
    page = int(params.get('page', 1))
    if addon:
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        items_per_page = 20
    xbmcplugin.setPluginCategory(handle, f'ČSFD / Nejlepší seriály - Stránka {page}')
    xbmcplugin.setContent(handle, 'tvshows')
    try:
        csfd_series = get_csfd_top_series(page, addon)
        if not csfd_series:
            ui.popinfo('Nepodařilo se načíst seriály z ČSFD žebříčku.', addon.getAddonInfo('name'))
            xbmcplugin.endOfDirectory(handle)
            return
        start_rank = (page - 1) * items_per_page + 1
        for i, csfd_show in enumerate(csfd_series):
            try:
                create_csfd_series_listitem(csfd_show, addon, handle, start_rank + i)
            except Exception as e:
                xbmc.log(f"[WCS ČSFD] Chyba při vytváření položky pro seriál: {csfd_show.get('csfd_title', 'Unknown')} - {e}", xbmc.LOGDEBUG)
                continue
        add_csfd_series_navigation(page, handle, addon)
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při zobrazování ČSFD seriálů: {e}", xbmc.LOGERROR)
        ui.popinfo(f"Chyba při načítání ČSFD seriálů: {e}", addon.getAddonInfo('name'))
    xbmcplugin.endOfDirectory(handle)

def create_csfd_series_listitem(csfd_show, addon, handle, rank=None):
    csfd_title = csfd_show.get('csfd_title', 'Neznámý seriál')
    csfd_year = csfd_show.get('csfd_year', '')
    csfd_rating = csfd_show.get('csfd_rating', '')
    
    # Kontrola dostupnosti TMDb API klíče před pokusem o párování
    tmdb_data = None
    try:
        # Pouze zkusíme získat API klíč, pokud se podaří, provedeme párování
        tmdb_handler.get_tmdb_api_key(addon)
        # Pokus o získání TMDb dat - pouze pro zobrazené seriály
        tmdb_data = match_csfd_series_to_tmdb(csfd_title, csfd_year, addon)
    except ValueError:
        # TMDb API klíč není nastaven - použijeme pouze ČSFD data
        tmdb_data = None
    except Exception:
        # Jiná chyba při párování - také použijeme pouze ČSFD data
        tmdb_data = None
    
    if rank:
        label = f"{rank}. {csfd_title}"
    else:
        label = csfd_title
    if csfd_year:
        label += f" ({csfd_year})"
    if csfd_rating:
        label += f" - {csfd_rating}%"
    listitem = xbmcgui.ListItem(label=label)
    info = {
        'title': csfd_title,
        'year': int(csfd_year) if csfd_year else 0,
        'mediatype': 'tvshow'
    }
    if tmdb_data:
        if tmdb_data.get('overview'):
            info['plot'] = tmdb_data['overview']
        if tmdb_data.get('vote_average'):
            info['rating'] = float(tmdb_data['vote_average'])
        poster_path = tmdb_data.get('poster_path')
        if poster_path:
            poster_url = f"https://image.tmdb.org/t/p/w500{poster_path}"
            listitem.setArt({'thumb': poster_url, 'poster': poster_url})
    
    # Pokud nemáme TMDb data, použijeme ČSFD informace
    if not tmdb_data:
        # Sestavení popisu z dostupných ČSFD dat  
        plot_parts = []
        if csfd_show.get('csfd_genres'):
            plot_parts.append(f"Žánry: {csfd_show['csfd_genres']}")
        if csfd_show.get('csfd_countries'):
            plot_parts.append(f"Země: {csfd_show['csfd_countries']}")
        if csfd_rating and csfd_show.get('csfd_rating_count'):
            plot_parts.append(f"Hodnocení ČSFD: {csfd_rating}% ({csfd_show['csfd_rating_count']} hodnocení)")
        
        if plot_parts:
            info['plot'] = '\n'.join(plot_parts)
    
    utils.set_video_info_tag(listitem, info)
    
    # Kontextové menu - pouze pokud máme TMDb data
    if tmdb_data and tmdb_data.get('id'):
        from wcs.ui.ContextMenu import create_series_context_menu
        commands = create_series_context_menu(
            addon=addon,
            tmdb_id=tmdb_data['id'],
            name=csfd_title,
            year=csfd_year,
            plot=info.get('plot', ''),
            poster=f"https://image.tmdb.org/t/p/w500{tmdb_data.get('poster_path')}" if tmdb_data.get('poster_path') else '',
            is_in_my_series=False,
            original_name=csfd_title
        )
        menu_context.add_legacy(listitem, commands)
    else:
        # Kontextové menu pouze s ČSFD odkazy
        csfd_url = csfd_show.get('csfd_url', '')
        if csfd_url:
            commands = [
                ("Otevřít na ČSFD", f"RunPlugin(plugin://{addon.getAddonInfo('id')}?action=open_csfd_url&url={quote_plus(csfd_url)})")
            ]
            menu_context.add_legacy(listitem, commands)
    
    # Defaultní akce: zobrazení seznamu sezón
    if tmdb_data and tmdb_data.get('id'):
        # Máme TMDb data - použijeme standardní TMDb zobrazení sezón
        default_url = f"plugin://{addon.getAddonInfo('id')}?action=display_series_seasons&series_id={tmdb_data['id']}&name={quote_plus(csfd_title)}"
    else:
        # Pokus o použití ČSFD systému bez TMDb API klíče
        csfd_url = csfd_show.get('csfd_url', '')
        series_csfd_id = None
        
        if csfd_url:
            # Extrahuj ČSFD ID z URL
            series_csfd_id = extract_csfd_id_from_url(csfd_url)
        
        if series_csfd_id:
            # Použij nový ČSFD systém pro zobrazení sezón
            default_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_series_seasons&series_csfd_id={series_csfd_id}&series_name={quote_plus(csfd_title)}"
        else:
            # Fallback na vyhledávání pokud se nepodařilo získat ČSFD ID
            search_query = f"{csfd_title} {csfd_year}".strip()
            default_url = f"plugin://{addon.getAddonInfo('id')}?action=search&what={quote_plus(search_query)}&handle={handle}"
    
    xbmcplugin.addDirectoryItem(handle, default_url, listitem, True)

def add_csfd_series_navigation(current_page, handle, addon):
    if addon:
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        items_per_page = 20
    total_series = 1000
    max_page = (total_series + items_per_page - 1) // items_per_page
    if current_page > 1:
        prev_item = xbmcgui.ListItem(label=f"<< Předchozí stránka ({current_page - 1})")
        prev_item.setArt({'icon': 'DefaultFolderBack.png'})
        prev_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_top_series&page={current_page - 1}"
        xbmcplugin.addDirectoryItem(handle, prev_url, prev_item, True)
    if current_page < max_page:
        next_item = xbmcgui.ListItem(label=f"Následující stránka ({current_page + 1}) >>")
        next_item.setArt({'icon': 'DefaultFolder.png'})
        next_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_top_series&page={current_page + 1}"
        xbmcplugin.addDirectoryItem(handle, next_url, next_item, True)

# --- ČSFD NEJOBLÍBENĚJŠÍ SERIÁLY ---

def get_csfd_favorite_series(page=1, addon=None):
    """
    Získá nejoblíbenější seriály z ČSFD žebříčku s cacheováním a optimalizací.
    """
    if addon:
        cache_hours = int(addon.getSetting('csfd_cache_hours') or 24)
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        cache_hours = 24
        items_per_page = 20
    # Výpočet rozsahu seriálů pro tuto stránku
    start_rank = (page - 1) * items_per_page + 1
    end_rank = page * items_per_page
    csfd_start_page = ((start_rank - 1) // 100) + 1
    csfd_end_page = ((end_rank - 1) // 100) + 1
    all_series = []
    for csfd_page in range(csfd_start_page, csfd_end_page + 1):
        csfd_series = _fetch_csfd_favorite_series_page(csfd_page, addon, cache_hours)
        if csfd_series:
            all_series.extend(csfd_series)
    start_index = (start_rank - 1) % 100
    if csfd_start_page == csfd_end_page:
        return all_series[start_index:start_index + items_per_page]
    else:
        result = []
        current_index = start_index
        for csfd_page in range(csfd_start_page, csfd_end_page + 1):
            csfd_series = _fetch_csfd_favorite_series_page(csfd_page, addon, cache_hours)
            if not csfd_series:
                continue
            if csfd_page == csfd_start_page:
                result.extend(csfd_series[current_index:])
            elif csfd_page == csfd_end_page:
                end_index = (end_rank - 1) % 100 + 1
                result.extend(csfd_series[:end_index])
            else:
                result.extend(csfd_series)
            if len(result) >= items_per_page:
                break
        return result[:items_per_page]

def _fetch_csfd_favorite_series_page(page, addon, cache_hours):
    from_param = (page - 1) * 100 + 1
    url = f"https://www.csfd.cz/zebricky/serialy/nejoblibenejsi/?from={from_param}"
    endpoint = f"/csfd/favorite_series/page_{page}"
    params = {}
    def fetch_csfd_data():
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji stránku {page} z ČSFD žebříčku nejoblíbenějších seriálů", xbmc.LOGINFO)
            headers = {'User-Agent': 'Mozilla/5.0'}
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            return _parse_chart_response(response.text, url)  # stejný parser funguje i pro seriály
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování ČSFD nejoblíbenějších seriálů: {e}", xbmc.LOGERROR)
            return []
    series = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_data, expire_seconds=cache_hours * 3600)
    return series if series else []

def list_csfd_favorite_series(params, addon, handle):
    page = int(params.get('page', 1))
    if addon:
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        items_per_page = 20
    xbmcplugin.setPluginCategory(handle, f'ČSFD / Nejoblíbenější seriály - Stránka {page}')
    xbmcplugin.setContent(handle, 'tvshows')
    try:
        csfd_series = get_csfd_favorite_series(page, addon)
        if not csfd_series:
            ui.popinfo('Nepodařilo se načíst nejoblíbenější seriály z ČSFD žebříčku.', addon.getAddonInfo('name'))
            xbmcplugin.endOfDirectory(handle)
            return
        start_rank = (page - 1) * items_per_page + 1
        for i, csfd_show in enumerate(csfd_series):
            try:
                create_csfd_series_listitem(csfd_show, addon, handle, start_rank + i)
            except Exception as e:
                xbmc.log(f"[WCS ČSFD] Chyba při vytváření položky pro nejoblíbenější seriál: {csfd_show.get('csfd_title', 'Unknown')} - {e}", xbmc.LOGDEBUG)
                continue
        add_csfd_favorite_series_navigation(page, handle, addon)
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při zobrazování ČSFD nejoblíbenějších seriálů: {e}", xbmc.LOGERROR)
        ui.popinfo(f"Chyba při načítání ČSFD nejoblíbenějších seriálů: {e}", addon.getAddonInfo('name'))
    xbmcplugin.endOfDirectory(handle)

def add_csfd_favorite_series_navigation(current_page, handle, addon):
    if addon:
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        items_per_page = 20
    total_series = 1000
    max_page = (total_series + items_per_page - 1) // items_per_page
    if current_page > 1:
        prev_item = xbmcgui.ListItem(label=f"<< Předchozí stránka ({current_page - 1})")
        prev_item.setArt({'icon': 'DefaultFolderBack.png'})
        prev_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_favorite_series&page={current_page - 1}"
        xbmcplugin.addDirectoryItem(handle, prev_url, prev_item, True)
    if current_page < max_page:
        next_item = xbmcgui.ListItem(label=f"Následující stránka ({current_page + 1}) >>")
        next_item.setArt({'icon': 'DefaultFolder.png'})
        next_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_favorite_series&page={current_page + 1}"
        xbmcplugin.addDirectoryItem(handle, next_url, next_item, True)

# --- ČSFD NEJOBLÍBENĚJŠÍ FILMY ---

def get_csfd_favorite_movies(page=1, addon=None):
    """
    Získá nejoblíbenější filmy z ČSFD žebříčku s cacheováním a optimalizací.
    """
    if addon:
        cache_hours = int(addon.getSetting('csfd_cache_hours') or 24)
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        cache_hours = 24
        items_per_page = 20
    # Výpočet rozsahu filmů pro tuto stránku
    start_rank = (page - 1) * items_per_page + 1
    end_rank = page * items_per_page
    csfd_start_page = ((start_rank - 1) // 100) + 1
    csfd_end_page = ((end_rank - 1) // 100) + 1
    all_movies = []
    for csfd_page in range(csfd_start_page, csfd_end_page + 1):
        csfd_movies = _fetch_csfd_favorite_movies_page(csfd_page, addon, cache_hours)
        if csfd_movies:
            all_movies.extend(csfd_movies)
    start_index = (start_rank - 1) % 100
    if csfd_start_page == csfd_end_page:
        return all_movies[start_index:start_index + items_per_page]
    else:
        result = []
        current_index = start_index
        for csfd_page in range(csfd_start_page, csfd_end_page + 1):
            csfd_movies = _fetch_csfd_favorite_movies_page(csfd_page, addon, cache_hours)
            if not csfd_movies:
                continue
            if csfd_page == csfd_start_page:
                result.extend(csfd_movies[current_index:])
            elif csfd_page == csfd_end_page:
                end_index = (end_rank - 1) % 100 + 1
                result.extend(csfd_movies[:end_index])
            else:
                result.extend(csfd_movies)
            if len(result) >= items_per_page:
                break
        return result[:items_per_page]

def _fetch_csfd_favorite_movies_page(page, addon, cache_hours):
    from_param = (page - 1) * 100 + 1
    url = f"https://www.csfd.cz/zebricky/filmy/nejoblibenejsi/?from={from_param}"
    endpoint = f"/csfd/favorite_movies/page_{page}"
    params = {}
    def fetch_csfd_data():
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji stránku {page} z ČSFD žebříčku nejoblíbenějších filmů", xbmc.LOGINFO)
            headers = {'User-Agent': 'Mozilla/5.0'}
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            return _parse_chart_response(response.text, url)
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování ČSFD nejoblíbenějších filmů: {e}", xbmc.LOGERROR)
            return []
    movies = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_data, expire_seconds=cache_hours * 3600)
    return movies if movies else []

def list_csfd_favorite_movies(params, addon, handle):
    page = int(params.get('page', 1))
    if addon:
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        items_per_page = 20
    xbmcplugin.setPluginCategory(handle, f'ČSFD / Nejoblíbenější filmy - Stránka {page}')
    xbmcplugin.setContent(handle, 'movies')
    try:
        csfd_movies = get_csfd_favorite_movies(page, addon)
        if not csfd_movies:
            ui.popinfo('Nepodařilo se načíst nejoblíbenější filmy z ČSFD žebříčku.', addon.getAddonInfo('name'))
            xbmcplugin.endOfDirectory(handle)
            return
        start_rank = (page - 1) * items_per_page + 1
        for i, csfd_movie in enumerate(csfd_movies):
            try:
                create_csfd_movie_listitem(csfd_movie, addon, handle, start_rank + i)
            except Exception as e:
                xbmc.log(f"[WCS ČSFD] Chyba při vytváření položky pro nejoblíbenější film: {csfd_movie.get('csfd_title', 'Unknown')} - {e}", xbmc.LOGDEBUG)
                continue
        add_csfd_favorite_movies_navigation(page, handle, addon)
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při zobrazování ČSFD nejoblíbenějších filmů: {e}", xbmc.LOGERROR)
        ui.popinfo(f"Chyba při načítání ČSFD nejoblíbenějších filmů: {e}", addon.getAddonInfo('name'))
    xbmcplugin.endOfDirectory(handle)

def add_csfd_favorite_movies_navigation(current_page, handle, addon):
    if addon:
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        items_per_page = 20
    total_movies = 1000
    max_page = (total_movies + items_per_page - 1) // items_per_page
    if current_page > 1:
        prev_item = xbmcgui.ListItem(label=f"<< Předchozí stránka ({current_page - 1})")
        prev_item.setArt({'icon': 'DefaultFolderBack.png'})
        prev_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_favorite_movies&page={current_page - 1}"
        xbmcplugin.addDirectoryItem(handle, prev_url, prev_item, True)
    if current_page < max_page:
        next_item = xbmcgui.ListItem(label=f"Následující stránka ({current_page + 1}) >>")
        next_item.setArt({'icon': 'DefaultFolder.png'})
        next_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_favorite_movies&page={current_page + 1}"
        xbmcplugin.addDirectoryItem(handle, next_url, next_item, True)

# --- ČSFD NEJROZPORUPLNĚJŠÍ FILMY ---

def get_csfd_controversial_movies(page=1, addon=None):
    """
    Získá nejrozporuplnější filmy z ČSFD žebříčku s cacheováním a optimalizací.
    """
    if addon:
        cache_hours = int(addon.getSetting('csfd_cache_hours') or 24)
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        cache_hours = 24
        items_per_page = 20
    # Výpočet rozsahu filmů pro tuto stránku
    start_rank = (page - 1) * items_per_page + 1
    end_rank = page * items_per_page
    csfd_start_page = ((start_rank - 1) // 100) + 1
    csfd_end_page = ((end_rank - 1) // 100) + 1
    all_movies = []
    for csfd_page in range(csfd_start_page, csfd_end_page + 1):
        csfd_movies = _fetch_csfd_controversial_movies_page(csfd_page, addon, cache_hours)
        if csfd_movies:
            all_movies.extend(csfd_movies)
    start_index = (start_rank - 1) % 100
    if csfd_start_page == csfd_end_page:
        return all_movies[start_index:start_index + items_per_page]
    else:
        result = []
        current_index = start_index
        for csfd_page in range(csfd_start_page, csfd_end_page + 1):
            csfd_movies = _fetch_csfd_controversial_movies_page(csfd_page, addon, cache_hours)
            if not csfd_movies:
                continue
            if csfd_page == csfd_start_page:
                result.extend(csfd_movies[current_index:])
            elif csfd_page == csfd_end_page:
                end_index = (end_rank - 1) % 100 + 1
                result.extend(csfd_movies[:end_index])
            else:
                result.extend(csfd_movies)
            if len(result) >= items_per_page:
                break
        return result[:items_per_page]

def _fetch_csfd_controversial_movies_page(page, addon, cache_hours):
    from_param = (page - 1) * 100 + 1
    url = f"https://www.csfd.cz/zebricky/filmy/nejrozporuplnejsi/?from={from_param}"
    endpoint = f"/csfd/controversial_movies/page_{page}"
    params = {}
    def fetch_csfd_data():
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji stránku {page} z ČSFD žebříčku nejrozporuplnějších filmů", xbmc.LOGINFO)
            headers = {'User-Agent': 'Mozilla/5.0'}
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            return _parse_chart_response(response.text, url)
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování ČSFD nejrozporuplnějších filmů: {e}", xbmc.LOGERROR)
            return []
    movies = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_data, expire_seconds=cache_hours * 3600)
    return movies if movies else []

def list_csfd_controversial_movies(params, addon, handle):
    page = int(params.get('page', 1))
    if addon:
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        items_per_page = 20
    xbmcplugin.setPluginCategory(handle, f'ČSFD / Nejrozporuplnější filmy - Stránka {page}')
    xbmcplugin.setContent(handle, 'movies')
    try:
        csfd_movies = get_csfd_controversial_movies(page, addon)
        if not csfd_movies:
            ui.popinfo('Nepodařilo se načíst nejrozporuplnější filmy z ČSFD žebříčku.', addon.getAddonInfo('name'))
            xbmcplugin.endOfDirectory(handle)
            return
        start_rank = (page - 1) * items_per_page + 1
        for i, csfd_movie in enumerate(csfd_movies):
            try:
                create_csfd_movie_listitem(csfd_movie, addon, handle, start_rank + i)
            except Exception as e:
                xbmc.log(f"[WCS ČSFD] Chyba při vytváření položky pro nejrozporuplnější film: {csfd_movie.get('csfd_title', 'Unknown')} - {e}", xbmc.LOGDEBUG)
                continue
        add_csfd_controversial_movies_navigation(page, handle, addon)
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při zobrazování ČSFD nejrozporuplnějších filmů: {e}", xbmc.LOGERROR)
        ui.popinfo(f"Chyba při načítání ČSFD nejrozporuplnějších filmů: {e}", addon.getAddonInfo('name'))
    xbmcplugin.endOfDirectory(handle)

def add_csfd_controversial_movies_navigation(current_page, handle, addon):
    if addon:
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        items_per_page = 20
    total_movies = 1000
    max_page = (total_movies + items_per_page - 1) // items_per_page
    if current_page > 1:
        prev_item = xbmcgui.ListItem(label=f"<< Předchozí stránka ({current_page - 1})")
        prev_item.setArt({'icon': 'DefaultFolderBack.png'})
        prev_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_controversial_movies&page={current_page - 1}"
        xbmcplugin.addDirectoryItem(handle, prev_url, prev_item, True)
    if current_page < max_page:
        next_item = xbmcgui.ListItem(label=f"Následující stránka ({current_page + 1}) >>")
        next_item.setArt({'icon': 'DefaultFolder.png'})
        next_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_controversial_movies&page={current_page + 1}"
        xbmcplugin.addDirectoryItem(handle, next_url, next_item, True)

# --- ČSFD NEJHORŠÍ FILMY ---

def get_csfd_worst_movies(page=1, addon=None):
    """
    Získá nejhorší filmy z ČSFD žebříčku s cacheováním a optimalizací.
    """
    if addon:
        cache_hours = int(addon.getSetting('csfd_cache_hours') or 24)
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        cache_hours = 24
        items_per_page = 20
    # Výpočet rozsahu filmů pro tuto stránku
    start_rank = (page - 1) * items_per_page + 1
    end_rank = page * items_per_page
    csfd_start_page = ((start_rank - 1) // 100) + 1
    csfd_end_page = ((end_rank - 1) // 100) + 1
    all_movies = []
    for csfd_page in range(csfd_start_page, csfd_end_page + 1):
        csfd_movies = _fetch_csfd_worst_movies_page(csfd_page, addon, cache_hours)
        if csfd_movies:
            all_movies.extend(csfd_movies)
    start_index = (start_rank - 1) % 100
    if csfd_start_page == csfd_end_page:
        return all_movies[start_index:start_index + items_per_page]
    else:
        result = []
        current_index = start_index
        for csfd_page in range(csfd_start_page, csfd_end_page + 1):
            csfd_movies = _fetch_csfd_worst_movies_page(csfd_page, addon, cache_hours)
            if not csfd_movies:
                continue
            if csfd_page == csfd_start_page:
                result.extend(csfd_movies[current_index:])
            elif csfd_page == csfd_end_page:
                end_index = (end_rank - 1) % 100 + 1
                result.extend(csfd_movies[:end_index])
            else:
                result.extend(csfd_movies)
            if len(result) >= items_per_page:
                break
        return result[:items_per_page]

def _fetch_csfd_worst_movies_page(page, addon, cache_hours):
    from_param = (page - 1) * 100 + 1
    url = f"https://www.csfd.cz/zebricky/filmy/nejhorsi/?from={from_param}"
    endpoint = f"/csfd/worst_movies/page_{page}"
    params = {}
    def fetch_csfd_data():
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji stránku {page} z ČSFD žebříčku nejhorších filmů", xbmc.LOGINFO)
            headers = {'User-Agent': 'Mozilla/5.0'}
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            return _parse_chart_response(response.text, url)
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování ČSFD nejhorších filmů: {e}", xbmc.LOGERROR)
            return []
    movies = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_data, expire_seconds=cache_hours * 3600)
    return movies if movies else []

def list_csfd_worst_movies(params, addon, handle):
    page = int(params.get('page', 1))
    if addon:
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        items_per_page = 20
    xbmcplugin.setPluginCategory(handle, f'ČSFD / Nejhorší filmy - Stránka {page}')
    xbmcplugin.setContent(handle, 'movies')
    try:
        csfd_movies = get_csfd_worst_movies(page, addon)
        if not csfd_movies:
            ui.popinfo('Nepodařilo se načíst nejhorší filmy z ČSFD žebříčku.', addon.getAddonInfo('name'))
            xbmcplugin.endOfDirectory(handle)
            return
        start_rank = (page - 1) * items_per_page + 1
        for i, csfd_movie in enumerate(csfd_movies):
            try:
                create_csfd_movie_listitem(csfd_movie, addon, handle, start_rank + i)
            except Exception as e:
                xbmc.log(f"[WCS ČSFD] Chyba při vytváření položky pro nejhorší film: {csfd_movie.get('csfd_title', 'Unknown')} - {e}", xbmc.LOGDEBUG)
                continue
        add_csfd_worst_movies_navigation(page, handle, addon)
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při zobrazování ČSFD nejhorších filmů: {e}", xbmc.LOGERROR)
        ui.popinfo(f"Chyba při načítání ČSFD nejhorších filmů: {e}", addon.getAddonInfo('name'))
    xbmcplugin.endOfDirectory(handle)

def add_csfd_worst_movies_navigation(current_page, handle, addon):
    if addon:
        items_per_page = int(addon.getSetting('csfd_items_per_page') or 20)
    else:
        items_per_page = 20
    total_movies = 1000
    max_page = (total_movies + items_per_page - 1) // items_per_page
    if current_page > 1:
        prev_item = xbmcgui.ListItem(label=f"<< Předchozí stránka ({current_page - 1})")
        prev_item.setArt({'icon': 'DefaultFolderBack.png'})
        prev_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_worst_movies&page={current_page - 1}"
        xbmcplugin.addDirectoryItem(handle, prev_url, prev_item, True)
    if current_page < max_page:
        next_item = xbmcgui.ListItem(label=f"Následující stránka ({current_page + 1}) >>")
        next_item.setArt({'icon': 'DefaultFolder.png'})
        next_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_worst_movies&page={current_page + 1}"
        xbmcplugin.addDirectoryItem(handle, next_url, next_item, True)

# --- ČSFD NEJROZPORUPLNĚJŠÍ SERIÁLY ---

def get_csfd_controversial_series(page=1, addon=None):
    """
    Získá nejrozporuplnější seriály z ČSFD žebříčku s cacheováním a optimalizací.
    """
    if addon:
        cache_hours = int(addon.getSetting('csfd_cache_hours') or 24)
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        cache_hours = 24
        items_per_page = 20
    # Výpočet rozsahu seriálů pro tuto stránku
    start_rank = (page - 1) * items_per_page + 1
    end_rank = page * items_per_page
    csfd_start_page = ((start_rank - 1) // 100) + 1
    csfd_end_page = ((end_rank - 1) // 100) + 1
    all_series = []
    for csfd_page in range(csfd_start_page, csfd_end_page + 1):
        csfd_series = _fetch_csfd_controversial_series_page(csfd_page, addon, cache_hours)
        if csfd_series:
            all_series.extend(csfd_series)
    start_index = (start_rank - 1) % 100
    if csfd_start_page == csfd_end_page:
        return all_series[start_index:start_index + items_per_page]
    else:
        result = []
        current_index = start_index
        for csfd_page in range(csfd_start_page, csfd_end_page + 1):
            csfd_series = _fetch_csfd_controversial_series_page(csfd_page, addon, cache_hours)
            if not csfd_series:
                continue
            if csfd_page == csfd_start_page:
                result.extend(csfd_series[current_index:])
            elif csfd_page == csfd_end_page:
                end_index = (end_rank - 1) % 100 + 1
                result.extend(csfd_series[:end_index])
            else:
                result.extend(csfd_series)
            if len(result) >= items_per_page:
                break
        return result[:items_per_page]

def _fetch_csfd_controversial_series_page(page, addon, cache_hours):
    from_param = (page - 1) * 100 + 1
    url = f"https://www.csfd.cz/zebricky/serialy/nejrozporuplnejsi/?from={from_param}"
    endpoint = f"/csfd/controversial_series/page_{page}"
    params = {}
    def fetch_csfd_data():
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji stránku {page} z ČSFD žebříčku nejrozporuplnějších seriálů", xbmc.LOGINFO)
            headers = {'User-Agent': 'Mozilla/5.0'}
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            return _parse_chart_response(response.text, url)  # stejný parser funguje i pro seriály
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování ČSFD nejrozporuplnějších seriálů: {e}", xbmc.LOGERROR)
            return []
    series = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_data, expire_seconds=cache_hours * 3600)
    return series if series else []

def list_csfd_controversial_series(params, addon, handle):
    page = int(params.get('page', 1))
    if addon:
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        items_per_page = 20
    xbmcplugin.setPluginCategory(handle, f'ČSFD / Nejrozporuplnější seriály - Stránka {page}')
    xbmcplugin.setContent(handle, 'tvshows')
    try:
        csfd_series = get_csfd_controversial_series(page, addon)
        if not csfd_series:
            ui.popinfo('Nepodařilo se načíst nejrozporuplnější seriály z ČSFD žebříčku.', addon.getAddonInfo('name'))
            xbmcplugin.endOfDirectory(handle)
            return
        start_rank = (page - 1) * items_per_page + 1
        for i, csfd_show in enumerate(csfd_series):
            try:
                create_csfd_series_listitem(csfd_show, addon, handle, start_rank + i)
            except Exception as e:
                xbmc.log(f"[WCS ČSFD] Chyba při vytváření položky pro nejrozporuplnější seriál: {csfd_show.get('csfd_title', 'Unknown')} - {e}", xbmc.LOGDEBUG)
                continue
        add_csfd_controversial_series_navigation(page, handle, addon)
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při zobrazování ČSFD nejrozporuplnějších seriálů: {e}", xbmc.LOGERROR)
        ui.popinfo(f"Chyba při načítání ČSFD nejrozporuplnějších seriálů: {e}", addon.getAddonInfo('name'))
    xbmcplugin.endOfDirectory(handle)

def add_csfd_controversial_series_navigation(current_page, handle, addon):
    if addon:
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        items_per_page = 20
    total_series = 1000
    max_page = (total_series + items_per_page - 1) // items_per_page
    if current_page > 1:
        prev_item = xbmcgui.ListItem(label=f"<< Předchozí stránka ({current_page - 1})")
        prev_item.setArt({'icon': 'DefaultFolderBack.png'})
        prev_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_controversial_series&page={current_page - 1}"
        xbmcplugin.addDirectoryItem(handle, prev_url, prev_item, True)
    if current_page < max_page:
        next_item = xbmcgui.ListItem(label=f"Následující stránka ({current_page + 1}) >>")
        next_item.setArt({'icon': 'DefaultFolder.png'})
        next_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_controversial_series&page={current_page + 1}"
        xbmcplugin.addDirectoryItem(handle, next_url, next_item, True)

# --- ČSFD NEJHORŠÍ SERIÁLY ---

def get_csfd_worst_series(page=1, addon=None):
    """
    Získá nejhorší seriály z ČSFD žebříčku s cacheováním a optimalizací.
    """
    if addon:
        cache_hours = int(addon.getSetting('csfd_cache_hours') or 24)
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        cache_hours = 24
        items_per_page = 20
    # Výpočet rozsahu seriálů pro tuto stránku
    start_rank = (page - 1) * items_per_page + 1
    end_rank = page * items_per_page
    csfd_start_page = ((start_rank - 1) // 100) + 1
    csfd_end_page = ((end_rank - 1) // 100) + 1
    all_series = []
    for csfd_page in range(csfd_start_page, csfd_end_page + 1):
        csfd_series = _fetch_csfd_worst_series_page(csfd_page, addon, cache_hours)
        if csfd_series:
            all_series.extend(csfd_series)
    start_index = (start_rank - 1) % 100
    if csfd_start_page == csfd_end_page:
        return all_series[start_index:start_index + items_per_page]
    else:
        result = []
        current_index = start_index
        for csfd_page in range(csfd_start_page, csfd_end_page + 1):
            csfd_series = _fetch_csfd_worst_series_page(csfd_page, addon, cache_hours)
            if not csfd_series:
                continue
            if csfd_page == csfd_start_page:
                result.extend(csfd_series[current_index:])
            elif csfd_page == csfd_end_page:
                end_index = (end_rank - 1) % 100 + 1
                result.extend(csfd_series[:end_index])
            else:
                result.extend(csfd_series)
            if len(result) >= items_per_page:
                break
        return result[:items_per_page]

def _fetch_csfd_worst_series_page(page, addon, cache_hours):
    from_param = (page - 1) * 100 + 1
    url = f"https://www.csfd.cz/zebricky/serialy/nejhorsi/?from={from_param}"
    endpoint = f"/csfd/worst_series/page_{page}"
    params = {}
    def fetch_csfd_data():
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji stránku {page} z ČSFD žebříčku nejhorších seriálů", xbmc.LOGINFO)
            headers = {'User-Agent': 'Mozilla/5.0'}
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            return _parse_chart_response(response.text, url)  # stejný parser funguje i pro seriály
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování ČSFD nejhorších seriálů: {e}", xbmc.LOGERROR)
            return []
    series = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_data, expire_seconds=cache_hours * 3600)
    return series if series else []

def list_csfd_worst_series(params, addon, handle):
    page = int(params.get('page', 1))
    if addon:
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        items_per_page = 20
    xbmcplugin.setPluginCategory(handle, f'ČSFD / Nejhorší seriály - Stránka {page}')
    xbmcplugin.setContent(handle, 'tvshows')
    try:
        csfd_series = get_csfd_worst_series(page, addon)
        if not csfd_series:
            ui.popinfo('Nepodařilo se načíst nejhorší seriály z ČSFD žebříčku.', addon.getAddonInfo('name'))
            xbmcplugin.endOfDirectory(handle)
            return
        start_rank = (page - 1) * items_per_page + 1
        for i, csfd_show in enumerate(csfd_series):
            try:
                create_csfd_series_listitem(csfd_show, addon, handle, start_rank + i)
            except Exception as e:
                xbmc.log(f"[WCS ČSFD] Chyba při vytváření položky pro nejhorší seriál: {csfd_show.get('csfd_title', 'Unknown')} - {e}", xbmc.LOGDEBUG)
                continue
        add_csfd_worst_series_navigation(page, handle, addon)
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při zobrazování ČSFD nejhorších seriálů: {e}", xbmc.LOGERROR)
        ui.popinfo(f"Chyba při načítání ČSFD nejhorších seriálů: {e}", addon.getAddonInfo('name'))
    xbmcplugin.endOfDirectory(handle)

def add_csfd_worst_series_navigation(current_page, handle, addon):
    if addon:
        items_per_page = int(addon.getSetting('csfd_series_items_per_page') or 20)
    else:
        items_per_page = 20
    total_series = 1000
    max_page = (total_series + items_per_page - 1) // items_per_page
    if current_page > 1:
        prev_item = xbmcgui.ListItem(label=f"<< Předchozí stránka ({current_page - 1})")
        prev_item.setArt({'icon': 'DefaultFolderBack.png'})
        prev_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_worst_series&page={current_page - 1}"
        xbmcplugin.addDirectoryItem(handle, prev_url, prev_item, True)
    if current_page < max_page:
        next_item = xbmcgui.ListItem(label=f"Následující stránka ({current_page + 1}) >>")
        next_item.setArt({'icon': 'DefaultFolder.png'})
        next_url = f"plugin://{addon.getAddonInfo('id')}?action=csfd_worst_series&page={current_page + 1}"
        xbmcplugin.addDirectoryItem(handle, next_url, next_item, True)

# --- ČSFD SERIÁLY BEZ TMDb API KLÍČE ---

def extract_csfd_id_from_url(csfd_url):
    """
    Extrahuje ČSFD ID z URL pomocí regex.
    
    Args:
        csfd_url (str): URL filmu/seriálu na ČSFD
        
    Returns:
        str: ČSFD ID nebo None pokud se nepodařilo extrahovat
    """
    try:
        # Pattern pro extrakci ID z ČSFD URL: /film/{ID}-{slug}
        match = re.search(r'/film/(\d+)-', csfd_url)
        if match:
            return match.group(1)
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při extrakci ČSFD ID z URL {csfd_url}: {e}", xbmc.LOGDEBUG)
    return None


def parse_csfd_series_seasons(series_csfd_id, series_name):
    """
    Parsuje seznam sezón ze ČSFD stránky seriálu.
    
    Args:
        series_csfd_id (str): ČSFD ID seriálu
        series_name (str): Název seriálu
        
    Returns:
        list: Seznam slovníků s daty sezón ze ČSFD
    """
    if not series_csfd_id:
        return []
    
    # Sestavení URL pro hlavní stránku seriálu
    # Potřebujeme slug, zkusíme vytvořit základní URL a nechat ČSFD přesměrovat
    url = f"https://www.csfd.cz/film/{series_csfd_id}/prehled/"
    
    # Cache pro sezóny
    endpoint = f"/csfd/series_seasons/{series_csfd_id}"
    params = {'series_name': series_name}
    
    # DEBUG: Log cache klíče
    params_str = json.dumps(params, sort_keys=True, ensure_ascii=False)
    raw_key = f'{endpoint}|{params_str}'
    cache_key = hashlib.sha256(raw_key.encode('utf-8')).hexdigest()
    xbmc.log(f"[WCS ČSFD DEBUG] Cache klíč pro sezóny: {cache_key[:16]}... (endpoint: {endpoint})", xbmc.LOGINFO)
    
    # DEBUG: Zkontroluj jestli už je v cache
    cached_data = tmdb_cache.get_from_cache(endpoint, params, expire_seconds=7 * 24 * 3600)
    if cached_data is not None:
        xbmc.log(f"[WCS ČSFD DEBUG] Sezóny NALEZENY v cache! Počet: {len(cached_data)}", xbmc.LOGINFO)
        return cached_data if cached_data else []
    else:
        xbmc.log(f"[WCS ČSFD DEBUG] Sezóny NEJSOU v cache - bude se stahovat ze ČSFD", xbmc.LOGINFO)

    def fetch_csfd_seasons():
        """Funkce pro stažení dat sezón z ČSFD"""
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji sezóny seriálu {series_name} (ID: {series_csfd_id})", xbmc.LOGINFO)
            
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
            }
            
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            
            return parse_csfd_seasons_html(response.text, series_csfd_id, series_name)
            
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování sezón seriálu {series_name}: {e}", xbmc.LOGERROR)
            return []
    
    # Cache na 7 dní pro sezóny (méně se mění než žebříčky)
    seasons = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_seasons, expire_seconds=7 * 24 * 3600)
    return seasons if seasons else []


def parse_csfd_seasons_html(html, series_csfd_id, series_name):
    """
    Parsuje HTML stránky seriálu a extrahuje data sezón.
    
    Args:
        html (str): HTML obsah stránky seriálu
        series_csfd_id (str): ID seriálu
        series_name (str): Název seriálu
        
    Returns:
        list: Seznam slovníků s daty sezón
    """
    seasons = []
    
    try:
        # Hledáme odkazy na sezóny - ČSFD používá různé struktury
        # Pattern 1: Odkazy obsahující název sezóny
        season_patterns = [
            # Standardní odkazy na sezóny
            r'<a[^>]*href="(/film/' + re.escape(series_csfd_id) + r'-[^/]+/(\d+)-([^/"]+))[^"]*"[^>]*>([^<]+)</a>',
            # Odkazy s class obsahující season
            r'<a[^>]*class="[^"]*season[^"]*"[^>]*href="(/film/[^"]+)"[^>]*>([^<]+)</a>',
            # Obecné odkazy uvnitř season divů
            r'<div[^>]*season[^>]*>.*?<a[^>]*href="(/film/[^"]+)"[^>]*>([^<]+)</a>',
        ]
        
        for pattern in season_patterns:
            matches = re.findall(pattern, html, re.DOTALL | re.IGNORECASE)
            for match in matches:
                try:
                    if len(match) >= 4:  # První pattern
                        season_url = match[0]
                        season_id = match[1] 
                        season_slug = match[2]
                        season_title = re.sub(r'<[^>]+>', '', match[3]).strip()
                    else:  # Ostatní patterny
                        season_url = match[0]
                        season_title = re.sub(r'<[^>]+>', '', match[1]).strip()
                        
                        # Pokusíme se extrahovat season_id z URL
                        season_match = re.search(r'/(\d+)-([^/]+)/?$', season_url)
                        if season_match:
                            season_id = season_match.group(1)
                            season_slug = season_match.group(2)
                        else:
                            continue
                    
                    # Kontrola validity sezóny
                    if not season_title or not season_id:
                        continue
                    
                    # Vyfiltrujeme nesmyslné odkazy
                    if any(word in season_title.lower() for word in ['galerie', 'videa', 'recenze', 'diskuze', 'uživatelé']):
                        continue
                    
                    season_data = {
                        'season_id': season_id,
                        'season_name': season_title,
                        'season_url': f"https://www.csfd.cz{season_url}",
                        'series_csfd_id': series_csfd_id,
                        'series_name': series_name,
                        'season_slug': season_slug
                    }
                    
                    # Kontrola duplicit podle season_id
                    if not any(s.get('season_id') == season_id for s in seasons):
                        seasons.append(season_data)
                        
                except Exception as e:
                    xbmc.log(f"[WCS ČSFD] Chyba při parsování sezóny: {e}", xbmc.LOGDEBUG)
                    continue
        
        # Pokud nenajdeme žádné sezóny standardním způsobem, zkusíme fallback
        if not seasons:
            # Hledáme text "Sezóna" nebo "Season" s čísly
            fallback_patterns = [
                r'(?:Sezóna|Season)\s*(\d+)',
                r'(\d+)\.\s*(?:sezóna|season)',
            ]
            
            for pattern in fallback_patterns:
                matches = re.findall(pattern, html, re.IGNORECASE)
                for match in matches:
                    try:
                        season_num = match if isinstance(match, str) else match[0]
                        season_data = {
                            'season_id': f"{series_csfd_id}_s{season_num}",  # Fallback ID
                            'season_name': f"Sezóna {season_num}",
                            'season_url': f"https://www.csfd.cz/film/{series_csfd_id}/",
                            'series_csfd_id': series_csfd_id,
                            'series_name': series_name,
                            'season_slug': f"season-{season_num}"
                        }
                        
                        # Kontrola duplicit
                        if not any(s.get('season_id') == season_data['season_id'] for s in seasons):
                            seasons.append(season_data)
                            
                    except Exception as e:
                        xbmc.log(f"[WCS ČSFD] Chyba při fallback parsování sezóny: {e}", xbmc.LOGDEBUG)
                        continue
        
        xbmc.log(f"[WCS ČSFD] Úspěšně naparsováno {len(seasons)} sezón pro seriál {series_name}", xbmc.LOGINFO)
        
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při parsování HTML sezón: {e}", xbmc.LOGERROR)
    
    return seasons


def parse_csfd_season_episodes(series_csfd_id, season_csfd_id, season_name):
    """
    Parsuje seznam epizod z ČSFD stránky sezóny.
    
    Args:
        series_csfd_id (str): ČSFD ID seriálu
        season_csfd_id (str): ČSFD ID sezóny
        season_name (str): Název sezóny
        
    Returns:
        list: Seznam slovníků s daty epizod ze ČSFD
    """
    if not series_csfd_id or not season_csfd_id:
        return []
    
    # Sestavení URL pro stránku sezóny
    url = f"https://www.csfd.cz/film/{series_csfd_id}/{season_csfd_id}/prehled/"
    
    # Cache pro epizody sezóny
    endpoint = f"/csfd/season_episodes/{series_csfd_id}/{season_csfd_id}"
    params = {}  # Odstraněno season_name - způsobovalo to různé cache klíče pro stejnou sezónu
    
    # DEBUG: Log cache klíče
    import hashlib
    import json
    params_str = json.dumps(params, sort_keys=True, ensure_ascii=False)
    raw_key = f'{endpoint}|{params_str}'
    cache_key = hashlib.sha256(raw_key.encode('utf-8')).hexdigest()
    xbmc.log(f"[WCS ČSFD DEBUG] Cache klíč pro epizody: {cache_key[:16]}... (endpoint: {endpoint})", xbmc.LOGINFO)
    
    # DEBUG: Zkontroluj jestli už je v cache
    cached_data = tmdb_cache.get_from_cache(endpoint, params, expire_seconds=7 * 24 * 3600)
    if cached_data is not None:
        xbmc.log(f"[WCS ČSFD DEBUG] Epizody NALEZENY v cache! Počet: {len(cached_data)}", xbmc.LOGINFO)
        return cached_data if cached_data else []
    else:
        xbmc.log(f"[WCS ČSFD DEBUG] Epizody NEJSOU v cache - bude se stahovat ze ČSFD", xbmc.LOGINFO)

    def fetch_csfd_episodes():
        """Funkce pro stažení dat epizod z ČSFD"""
        try:
            xbmc.log(f"[WCS ČSFD] Stahuji epizody sezóny {season_name} (Series ID: {series_csfd_id}, Season ID: {season_csfd_id})", xbmc.LOGINFO)
            
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
            }
            
            response = requests.get(url, headers=headers, timeout=15)
            response.raise_for_status()
            response.encoding = 'utf-8'
            
            episodes_data = parse_csfd_episodes_html(response.text, series_csfd_id, season_csfd_id, season_name)
            xbmc.log(f"[WCS ČSFD DEBUG] Naparsováno {len(episodes_data)} epizod - ukládám do cache", xbmc.LOGINFO)
            return episodes_data
            
        except Exception as e:
            xbmc.log(f"[WCS ČSFD] Chyba při stahování epizod sezóny {season_name}: {e}", xbmc.LOGERROR)
            return []

    # Cache na 7 dní pro epizody  
    episodes = tmdb_cache.get_or_fetch(endpoint, params, fetch_csfd_episodes, expire_seconds=7 * 24 * 3600)
    xbmc.log(f"[WCS ČSFD DEBUG] Výsledek get_or_fetch: {len(episodes) if episodes else 0} epizod", xbmc.LOGINFO)
    return episodes if episodes else []


def parse_csfd_episodes_html(html, series_csfd_id, season_csfd_id, season_name):
    """
    Parsuje HTML stránky sezóny a extrahuje data epizod.
    
    Args:
        html (str): HTML obsah stránky sezóny
        series_csfd_id (str): ID seriálu  
        season_csfd_id (str): ID sezóny
        season_name (str): Název sezóny
        
    Returns:
        list: Seznam slovníků s daty epizod
    """
    episodes = []
    
    try:
        # ROZŠÍŘENÝ SEZNAM FILTROVACÍCH SLOV PRO NAVIGAČNÍ PRVKY
        navigation_filter_words = [
            'galerie', 'videa', 'recenze', 'diskuze', 'uživatelé', 'fotky', 'více',
            'přehled', 'zajímavosti', 'hrají', 'ocenění', 'ost', 'filmotéka', 
            'premiéry', 'tagy', 'související', 'podobné', 'předchozí', 'následující', 
            'stránka', 'stránek', 'obsah', 'tvůrci', 'tvorcovia', 'herci', 'všechny',
            'všetky', 'menu', 'navigace', 'navigácia', 'hlavní', 'zpět', 'back',
            'home', 'domů', 'odkazy', 'search', 'vyhledávání', 'hľadanie', 'čsfd',
            'film', 'seriál', 'série', 'séria', 'česko', 'slovensko', 'details',
            'popis', 'informácie', 'informace', 'overview', 'hodnotenie', 'hodnocení',
            'fanklub', 'top', 'žebříček', 'rebríček', 'nejlepší', 'najlepšie'
        ]
        
        # NOVÉ PATTERNY PRO TEXTOVÉ SEZNAMY EPIZOD - ZPŘÍSNĚNÉ
        episode_text_patterns = [
            # Pattern pro "Název epizody (S01E01)" nebo "Název epizody (E01)" - specifický
            r'([^(\n]+?)\s*\((?:S\d+)?E(\d+)\)',
            # Pattern pro "E01 - Název epizody" (musí začínat E)
            r'E(\d+)\s*[-–]\s*([^\n]+?)(?=\n|$|<)',
            # Pattern pro Český formát "Epizoda 1: Název" nebo "Díl 1 - Název"  
            r'(?:Epizoda|Díl)\s*(\d+)(?:\s*[:–-]\s*)([^\n]+?)(?=\n|$|<)',
            # Pattern pro číslovaný seznam epizod - pouze pokud je za číslem dvojtečka nebo pomlčka a název je dostatečně dlouhý
            r'^(\d{1,2})\s*[:–-]\s*([A-Za-z][^\n]{4,})(?=\n|$|<)',
        ]
        
        # Nejdřív zkusíme najít sekci s epizodami
        episode_section_matches = re.finditer(r'(?:epizod[yaiíě]|episodes?)\s*\((\d+)\)', html, re.IGNORECASE)
        
        for pattern in episode_text_patterns:
            matches = re.findall(pattern, html, re.MULTILINE | re.IGNORECASE)
            for match in matches:
                try:
                    episode_number = None
                    episode_title = None
                    
                    # Zpracování různých formátů matchů
                    if len(match) == 2:
                        if match[1].isdigit():  # První skupina je název, druhá číslo
                            episode_title = match[0].strip()
                            episode_number = match[1]
                        else:  # První skupina je číslo, druhá název
                            episode_number = match[0] if match[0] else match[1]
                            episode_title = match[1] if match[0] else match[0]
                    elif len(match) == 3:
                        # Tři skupiny - najdeme číslo a název
                        episode_number = match[0] or match[1]
                        episode_title = match[2]
                    else:
                        continue
                    
                    if not episode_title or not episode_number:
                        continue
                        
                    # Vyčistíme název epizody
                    episode_title = re.sub(r'<[^>]+>', '', episode_title).strip()
                    episode_title = re.sub(r'\s+', ' ', episode_title)
                    
                    # ROZŠÍŘENÉ FILTROVÁNÍ - kontrola všech navigačních slov
                    if any(word in episode_title.lower() for word in navigation_filter_words):
                        continue
                    
                    # DODATEČNÉ FILTRY PRO TYPICKÉ NAVIGAČNÍ FRÁZE
                    # Filtrování číslovaných navigačních prvků
                    if re.match(r'^\d+\s*(z|of|/)\s*\d+', episode_title.lower()):
                        continue
                    
                    # Filtrování URL fragmentů
                    if any(fragment in episode_title.lower() for fragment in ['.html', '.php', '.jsp', 'http', 'www', '.cz', '.sk']):
                        continue
                    
                    # Filtrování příliš krátkých nebo dlouhých názvů
                    if len(episode_title) < 3 or len(episode_title) > 80:
                        continue
                    
                    # Filtrování názvů obsahujících jen čísla a interpunkci
                    if re.match(r'^[\d\s\-–.,()]+$', episode_title):
                        continue
                    
                    # Kontrola, že číslo epizody je rozumné (1-999)
                    try:
                        episode_num_int = int(episode_number)
                        if episode_num_int < 1 or episode_num_int > 999:
                            continue
                    except ValueError:
                        continue
                    
                    episode_data = {
                        'episode_id': f"{season_csfd_id}_e{episode_number}",
                        'episode_name': episode_title,
                        'episode_number': episode_number,
                        'episode_url': f"https://www.csfd.cz/film/{series_csfd_id}/{season_csfd_id}/",
                        'series_csfd_id': series_csfd_id,
                        'season_csfd_id': season_csfd_id,
                        'season_name': season_name,
                        'episode_slug': f"episode-{episode_number}"
                    }
                    
                    # Kontrola duplicit podle čísla epizody
                    if not any(e.get('episode_number') == episode_number for e in episodes):
                        episodes.append(episode_data)
                        
                except Exception as e:
                    xbmc.log(f"[WCS ČSFD] Chyba při parsování textové epizody: {e}", xbmc.LOGDEBUG)
                    continue
        
        # FALLBACK - původní logika pro odkazy (zůstává pro zpětnou kompatibilitu)
        if not episodes:
            # Hledáme odkazy na epizody - ČSFD používá různé struktury
            episode_patterns = [
                # Standardní odkazy na epizody
                r'<a[^>]*href="(/film/' + re.escape(series_csfd_id) + r'-[^/]+/' + re.escape(season_csfd_id) + r'-[^/]+/(\d+)-([^/"]+))[^"]*"[^>]*>([^<]+)</a>',
                # Odkazy s class obsahující episode
                r'<a[^>]*class="[^"]*episode[^"]*"[^>]*href="(/film/[^"]+)"[^>]*>([^<]+)</a>',
                # Obecné odkazy uvnitř episode divů/řádků
                r'<(?:div|tr)[^>]*episode[^>]*>.*?<a[^>]*href="(/film/[^"]+)"[^>]*>([^<]+)</a>',
            ]
            
            for pattern in episode_patterns:
                matches = re.findall(pattern, html, re.DOTALL | re.IGNORECASE)
                for match in matches:
                    try:
                        if len(match) >= 4:  # První pattern
                            episode_url = match[0]
                            episode_id = match[1]
                            episode_slug = match[2]
                            episode_title = re.sub(r'<[^>]+>', '', match[3]).strip()
                        else:  # Ostatní patterny
                            episode_url = match[0]
                            episode_title = re.sub(r'<[^>]+>', '', match[1]).strip()
                            
                            # Pokusíme se extrahovat episode_id z URL
                            episode_match = re.search(r'/(\d+)-([^/]+)/?$', episode_url)
                            if episode_match:
                                episode_id = episode_match.group(1)
                                episode_slug = episode_match.group(2)
                            else:
                                continue
                        
                        # Kontrola validity epizody
                        if not episode_title or not episode_id:
                            continue
                        
                        # ROZŠÍŘENÉ FILTROVÁNÍ i pro fallback
                        if any(word in episode_title.lower() for word in navigation_filter_words):
                            continue
                        
                        # Pokusíme se najít číslo epizody v názvu
                        episode_number = None
                        episode_num_match = re.search(r'(?:epizoda|episode|díl)\s*(\d+)|(\d+)\s*\.?\s*(?:epizoda|episode|díl)', episode_title, re.IGNORECASE)
                        if episode_num_match:
                            episode_number = episode_num_match.group(1) or episode_num_match.group(2)
                        else:
                            # Pokusíme se najít číslo na začátku názvu
                            num_match = re.match(r'^(\d+)\.?\s*-?\s*', episode_title)
                            if num_match:
                                episode_number = num_match.group(1)
                        
                        episode_data = {
                            'episode_id': episode_id,
                            'episode_name': episode_title,
                            'episode_number': episode_number,
                            'episode_url': f"https://www.csfd.cz{episode_url}",
                            'series_csfd_id': series_csfd_id,
                            'season_csfd_id': season_csfd_id,
                            'season_name': season_name,
                            'episode_slug': episode_slug
                        }
                        
                        # Kontrola duplicit podle episode_id
                        if not any(e.get('episode_id') == episode_id for e in episodes):
                            episodes.append(episode_data)
                            
                    except Exception as e:
                        xbmc.log(f"[WCS ČSFD] Chyba při parsování epizody: {e}", xbmc.LOGDEBUG)
                        continue
        
        # FINÁLNÍ FALLBACK - hledáme čísla epizod v jakémkoliv textu (pouze pokud stále nemáme epizody)
        if not episodes:
            # Hledáme základní patterny pro čísla epizod
            fallback_matches = re.findall(r'(?:Epizoda|Episode|Díl)\s*(\d+)(?:\s*[:–-]\s*(.+?))?(?=<|$)', html, re.IGNORECASE)
            for match in fallback_matches:
                try:
                    episode_num = match[0]
                    episode_name = match[1].strip() if match[1] else f"Epizoda {episode_num}"
                    
                    # FILTROVÁNÍ i pro finální fallback
                    if any(word in episode_name.lower() for word in navigation_filter_words):
                        continue
                    
                    episode_data = {
                        'episode_id': f"{season_csfd_id}_e{episode_num}",  # Fallback ID
                        'episode_name': episode_name,
                        'episode_number': episode_num,
                        'episode_url': f"https://www.csfd.cz/film/{series_csfd_id}/{season_csfd_id}/",
                        'series_csfd_id': series_csfd_id,
                        'season_csfd_id': season_csfd_id,
                        'season_name': season_name,
                        'episode_slug': f"episode-{episode_num}"
                    }
                    
                    # Kontrola duplicit
                    if not any(e.get('episode_id') == episode_data['episode_id'] for e in episodes):
                        episodes.append(episode_data)
                        
                except Exception as e:
                    xbmc.log(f"[WCS ČSFD] Chyba při fallback parsování epizody: {e}", xbmc.LOGDEBUG)
                    continue
        
        xbmc.log(f"[WCS ČSFD] Úspěšně naparsováno {len(episodes)} epizod pro sezónu {season_name}", xbmc.LOGINFO)
        
    except Exception as e:
        xbmc.log(f"[WCS ČSFD] Chyba při parsování HTML epizod: {e}", xbmc.LOGERROR)
    
    return episodes