import sys
import xbmc
import xbmcgui
import xbmcplugin
import xbmcaddon
import xbmcvfs
import urllib.parse
import requests
import json
import time
import tempfile
import os
import uuid
import tempfile

ADDON = xbmcaddon.Addon()
ADDON_ID = ADDON.getAddonInfo('id')
ADDON_NAME = ADDON.getAddonInfo('name')
ADDON_VERSION = ADDON.getAddonInfo('version')
ADDON_PATH = ADDON.getAddonInfo('path')

TMDB_API_KEY = "a46c50a0ccb1bafe2b15665df7fad7e1"
TMDB_BASE_URL = "https://api.themoviedb.org/3"
IMAGE_BASE_URL = "https://image.tmdb.org/t/p/"
STREAM_API_URL = "https://tmkt-api-production.up.railway.app/debug/stream"
SUBTITLE_API_URL = "https://sub.wyzie.ru/search"

POSTER_SIZE = "w500"
BACKDROP_SIZE = "w1280"

ADDON_DATA_PATH = xbmcvfs.translatePath(f"special://profile/addon_data/{ADDON_ID}")
CLIENT_ID_FILE = os.path.join(ADDON_DATA_PATH, "client_id.txt")

PAID_API_CHECK_URL = "https://tmkt-api-production.up.railway.app/debug/validate_key"
PAID_CACHE_FILE = xbmcvfs.translatePath(f"special://profile/addon_data/{ADDON_ID}/paid_cache.json")

def is_paid_user(force_refresh=False):
    log(f"is_paid_user() called with force_refresh={force_refresh}", xbmc.LOGDEBUG)
    
    api_key = ADDON.getSetting("paid_api_key")
    if not api_key:
        log("No API key found in settings", xbmc.LOGDEBUG)
        return False

    api_key = api_key.strip()
    log(f"Using API key: {api_key[:8]}...", xbmc.LOGDEBUG)
    
    if not force_refresh and xbmcvfs.exists(PAID_CACHE_FILE):
        try:
            with xbmcvfs.File(PAID_CACHE_FILE, 'r') as f:
                cache_data = json.load(f)
                log(f"Cache data: {cache_data}", xbmc.LOGDEBUG)
                
                if cache_data.get("api_key") == api_key:
                    is_paid_cached = cache_data.get("is_paid", False)
                    log(f"Returning cached value: {is_paid_cached}", xbmc.LOGDEBUG)
                    return is_paid_cached
                else:
                    log(f"Cache mismatch, will validate with API", xbmc.LOGDEBUG)
        except Exception as e:
            log(f"Cache read error: {e}. Will validate with API.", xbmc.LOGWARNING)
    
    client_id = get_client_id()
    params = {
        "api_key": api_key,
        "client_id": client_id
    }
    
    log(f"Validating API key with backend...", xbmc.LOGDEBUG)
    
    is_paid = False
    http_status = 0
    response_text = ""
    
    try:
        resp = requests.get(PAID_API_CHECK_URL, params=params, timeout=10)
        http_status = resp.status_code
        response_text = resp.text[:200]
        
        log(f"Response status: {http_status}", xbmc.LOGDEBUG)
        log(f"Response: {response_text}", xbmc.LOGDEBUG)
        
        if resp.status_code == 200:
            result = resp.json()
            log(f"Parsed JSON: {result}", xbmc.LOGDEBUG)
            
            if isinstance(result, dict):
                is_paid = result.get("paid", False) or result.get("plan") == "paid"
                
                if is_paid:
                    log(f"API key is VALID and PAID", xbmc.LOGDEBUG)
                else:
                    log(f"API key is valid but NOT paid", xbmc.LOGDEBUG)
            else:
                log(f"Response is not a JSON object: {result}", xbmc.LOGERROR)
                is_paid = False
        else:
            log(f"HTTP error: {http_status}", xbmc.LOGERROR)
            is_paid = False
            
    except requests.exceptions.Timeout:
        log(f"Request timeout", xbmc.LOGERROR)
        is_paid = False
    except requests.exceptions.ConnectionError:
        log(f"Connection error", xbmc.LOGERROR)
        is_paid = False
    except Exception as e:
        log(f"Unexpected error: {str(e)}", xbmc.LOGERROR)
        is_paid = False
    
    log(f"Saving to cache: is_paid={is_paid}", xbmc.LOGDEBUG)
    try:
        folder = xbmcvfs.translatePath(f"special://profile/addon_data/{ADDON_ID}")
        if not xbmcvfs.exists(folder):
            xbmcvfs.mkdirs(folder)
            log(f"Created folder: {folder}", xbmc.LOGDEBUG)
        
        cache_data = {
            "api_key": api_key,
            "is_paid": is_paid,
            "timestamp": time.time(),
            "client_id": client_id,
            "last_checked": time.strftime("%Y-%m-%d %H:%M:%S"),
            "http_status": http_status
        }
        
        with xbmcvfs.File(PAID_CACHE_FILE, 'w') as f:
            json.dump(cache_data, f)
            log(f"Cache saved: {PAID_CACHE_FILE}", xbmc.LOGDEBUG)
            log(f"Cache content: {cache_data}", xbmc.LOGDEBUG)
            
    except Exception as e:
        log(f"Failed to save cache: {str(e)}", xbmc.LOGERROR)
    
    return is_paid

TV_WATCH_PROGRESS_FILE = os.path.join(ADDON_DATA_PATH, "tv_watch_progress.json")
TRAKT_CLIENT_ID = "5d6cc5885f09bab6380eec63405093a3b350e2134615cbc61e3b07b89bc87f65"
TRAKT_CLIENT_SECRET = "7f2b40f8b5b5edd9e0eb916c69772b49735b4d0fde0af33b469a5bd297f6a22e"
TRAKT_TOKEN_FILE = os.path.join(ADDON_DATA_PATH, "trakt_token.json")

def trakt_watchlist():
    if not is_paid_user():
        xbmcgui.Dialog().notification(ADDON_NAME, "Paid access required", xbmcgui.NOTIFICATION_ERROR)
        return

    headers = get_trakt_headers()
    if not headers:
        xbmcgui.Dialog().notification(ADDON_NAME, "Link Trakt account first", xbmcgui.NOTIFICATION_ERROR)
        return

    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    
    try:
        url = "https://api.trakt.tv/users/me/watchlist"
        log(f"Fetching complete Trakt watchlist from: {url}", xbmc.LOGDEBUG)
        
        response = requests.get(url, headers=headers, timeout=15)
        log(f"Trakt API response status: {response.status_code}", xbmc.LOGDEBUG)
        
        if response.status_code == 401 or response.status_code == 403:
            xbmcgui.Dialog().notification(ADDON_NAME, "Trakt token expired. Please relink", xbmcgui.NOTIFICATION_ERROR)
            if xbmcvfs.exists(TRAKT_TOKEN_FILE):
                xbmcvfs.delete(TRAKT_TOKEN_FILE)
            return
            
        response.raise_for_status()
        watchlist_items = response.json()
        
        log(f"Trakt watchlist has {len(watchlist_items)} total items", xbmc.LOGDEBUG)
        
        if not watchlist_items:
            xbmcgui.Dialog().notification(ADDON_NAME, "Watchlist is empty", xbmcgui.NOTIFICATION_INFO)
            xbmcplugin.endOfDirectory(handle)
            return
        
        movies = []
        tv_shows = []
        
        for item in watchlist_items:
            media_type = item.get('type', '')
            if media_type == 'movie':
                movies.append(item)
            elif media_type == 'show':
                tv_shows.append(item)
        
        log(f"Found {len(movies)} movies and {len(tv_shows)} TV shows in watchlist", xbmc.LOGDEBUG)
        
        if tv_shows:
            tv_header = xbmcgui.ListItem("=== TV SHOWS ===")
            tv_header.setArt({'icon': 'DefaultFolder.png'})
            tv_header.setInfo('video', {'title': "TV Shows in Watchlist"})
            xbmcplugin.addDirectoryItem(handle, "", tv_header, isFolder=False)
            
            for item in tv_shows:
                show = item.get('show', {})
                if not show:
                    continue
                    
                title = show.get('title', 'Unknown')
                year_str = str(show.get('year', ''))
                tmdb_id = show.get('ids', {}).get('tmdb')
                tvdb_id = show.get('ids', {}).get('tvdb')
                
                try:
                    year_int = int(year_str) if year_str and year_str.isdigit() else 0
                except:
                    year_int = 0
                
                label = f"{title} ({year_str})" if year_str and year_str != '0' else title
                li = xbmcgui.ListItem(label)
                
                poster = ""
                fanart = ""
                if tmdb_id:
                    try:
                        tmdb_details = tmdb.get_tv_details(tmdb_id)
                        if tmdb_details:
                            poster = build_image_url(tmdb_details.get("poster_path"), POSTER_SIZE)
                            fanart = build_image_url(tmdb_details.get("backdrop_path"), BACKDROP_SIZE)
                    except Exception as e:
                        log(f"Error getting TMDB details for {tmdb_id}: {e}", xbmc.LOGDEBUG)
                        pass
                
                li.setArt({
                    'icon': poster or 'DefaultVideo.png',
                    'thumb': poster or 'DefaultVideo.png',
                    'poster': poster or 'DefaultVideo.png',
                    'fanart': fanart or ADDON_PATH + "/fanart.jpg"
                })
                
                info = {
                    'title': title,
                    'year': year_int,
                    'tvshowtitle': title,
                    'mediatype': 'tvshow'
                }
                li.setInfo('video', info)
                
                context_menu_items = []
                
                if tmdb_id:
                    details_url = get_url(action="tv_details", id=tmdb_id, from_watchlist="true")
                    
                    if tvdb_id:
                        remove_url = get_url(action="trakt_remove_tv_watchlist", tvdb_id=tvdb_id)
                        context_menu_items.append(("Remove from Watchlist", f"RunPlugin({remove_url})"))
                    
                    li.addContextMenuItems(context_menu_items)
                    
                    xbmcplugin.addDirectoryItem(handle, details_url, li, isFolder=True)
        
        if movies:
            movie_header = xbmcgui.ListItem("=== MOVIES ===")
            movie_header.setArt({'icon': 'DefaultFolder.png'})
            movie_header.setInfo('video', {'title': "Movies in Watchlist"})
            xbmcplugin.addDirectoryItem(handle, "", movie_header, isFolder=False)
            
            for item in movies:
                movie = item.get('movie', {})
                if not movie:
                    continue
                    
                title = movie.get('title', 'Unknown')
                year_str = str(movie.get('year', ''))
                tmdb_id = movie.get('ids', {}).get('tmdb')
                imdb_id = movie.get('ids', {}).get('imdb', '')
                
                try:
                    year_int = int(year_str) if year_str and year_str.isdigit() else 0
                except:
                    year_int = 0
                
                label = f"{title} ({year_str})" if year_str and year_str != '0' else title
                li = xbmcgui.ListItem(label)
                
                poster = ""
                fanart = ""
                plot = ""
                rating = 0.0
                
                if tmdb_id:
                    try:
                        tmdb_details = tmdb.get_movie_details(tmdb_id)
                        if tmdb_details:
                            poster = build_image_url(tmdb_details.get("poster_path"), POSTER_SIZE)
                            fanart = build_image_url(tmdb_details.get("backdrop_path"), BACKDROP_SIZE)
                            plot = tmdb_details.get("overview", "")
                            rating = float(tmdb_details.get("vote_average", 0))
                    except Exception as e:
                        log(f"Error getting TMDB details for {tmdb_id}: {e}", xbmc.LOGDEBUG)
                        pass
                
                li.setArt({
                    'icon': poster or 'DefaultVideo.png',
                    'thumb': poster or 'DefaultVideo.png',
                    'poster': poster or 'DefaultVideo.png',
                    'fanart': fanart or ADDON_PATH + "/fanart.jpg"
                })
                
                info = {
                    'title': title,
                    'year': year_int,
                    'plot': plot,
                    'rating': rating,
                    'mediatype': 'movie'
                }
                li.setInfo('video', info)
                
                context_menu_items = []
                
                if imdb_id:
                    play_url = get_url(action="play_movie", ttid=imdb_id, title=title, from_watchlist="true")
                    context_menu_items.append(("Play", f"PlayMedia({play_url})"))
                    
                    if tmdb_id:
                        play_subs_url = get_url(action="play_movie_subs", ttid=imdb_id, tmdb_id=tmdb_id, title=title, from_watchlist="true")
                        context_menu_items.append(("Play with Subtitles", f"PlayMedia({play_subs_url})"))
                    
                    remove_url = get_url(action="trakt_remove_watchlist", imdb_id=imdb_id)
                    context_menu_items.append(("Remove from Watchlist", f"RunPlugin({remove_url})"))
                    
                    li.addContextMenuItems(context_menu_items)
                    
                    details_url = get_url(action="movie_details", id=tmdb_id if tmdb_id else 0)
                    xbmcplugin.addDirectoryItem(handle, details_url, li, isFolder=True)
        
        if not movies and not tv_shows:
            xbmcgui.Dialog().notification(ADDON_NAME, "Watchlist is empty", xbmcgui.NOTIFICATION_INFO)
        
        xbmcplugin.setContent(handle, 'videos')
        xbmcplugin.endOfDirectory(handle)
        
    except Exception as e:
        log(f"Trakt watchlist error: {str(e)}", xbmc.LOGERROR)
        xbmcgui.Dialog().notification(ADDON_NAME, f"Failed to load watchlist: {str(e)}", xbmcgui.NOTIFICATION_ERROR)
        xbmcplugin.endOfDirectory(handle)


def save_trakt_token(token_data):
    try:
        with open(TRAKT_TOKEN_FILE, "w") as f:
            json.dump(token_data, f)
        if 'username' in token_data:
            ADDON.setSetting("trakt_username", token_data['username'])
    except Exception as e:
        log(f"Failed saving Trakt token: {e}", xbmc.LOGERROR)

def load_trakt_token():
    if xbmcvfs.exists(TRAKT_TOKEN_FILE):
        try:
            with open(TRAKT_TOKEN_FILE, "r") as f:
                return json.load(f)
        except Exception:
            return None
    return None

def exchange_trakt_code(code):
    url = "https://api.trakt.tv/oauth/token"
    payload = {
        "code": code,
        "client_id": TRAKT_CLIENT_ID,
        "client_secret": TRAKT_CLIENT_SECRET,
        "redirect_uri": "urn:ietf:wg:oauth:2.0:oob",
        "grant_type": "authorization_code"
    }
    try:
        resp = requests.post(url, json=payload, timeout=15)
        resp.raise_for_status()
        token_data = resp.json()
        save_trakt_token(token_data)
        return token_data
    except Exception as e:
        log(f"Trakt linking failed: {e}", xbmc.LOGERROR)
        return None

def get_trakt_headers():
    token_data = load_trakt_token()
    if not token_data:
        return None
    return {
        "Authorization": f"Bearer {token_data['access_token']}",
        "Content-Type": "application/json",
        "trakt-api-version": "2",
        "trakt-api-key": TRAKT_CLIENT_ID
    }

def trakt_add_tv_to_watchlist_simple(tvdb_id):
    headers = get_trakt_headers()
    if not headers:
        xbmcgui.Dialog().notification(ADDON_NAME, "Link Trakt first", xbmcgui.NOTIFICATION_ERROR)
        return False
    
    payload = {"shows": [{"ids": {"tvdb": tvdb_id}}]}
    url = "https://api.trakt.tv/sync/watchlist"
    try:
        resp = requests.post(url, headers=headers, json=payload, timeout=15)
        if resp.status_code in (200, 201):
            xbmcgui.Dialog().notification(ADDON_NAME, "Added to watchlist", xbmcgui.NOTIFICATION_INFO)
            return True
        else:
            log(f"Failed to add TV to watchlist: {resp.status_code} - {resp.text}", xbmc.LOGERROR)
            return False
    except Exception as e:
        log(f"Error adding TV to watchlist: {e}", xbmc.LOGERROR)
        return False

def trakt_remove_tv_from_watchlist_simple(tvdb_id):
    headers = get_trakt_headers()
    if not headers:
        return False
    
    payload = {"shows": [{"ids": {"tvdb": tvdb_id}}]}
    url = "https://api.trakt.tv/sync/watchlist/remove"
    try:
        resp = requests.post(url, headers=headers, json=payload, timeout=15)
        if resp.status_code in (200, 201):
            log(f"Successfully removed TV show {tvdb_id} from watchlist", xbmc.LOGDEBUG)
            return True
        else:
            log(f"Failed to remove TV from watchlist: {resp.status_code} - {resp.text}", xbmc.LOGERROR)
            return False
    except Exception as e:
        log(f"Error removing TV from watchlist: {e}", xbmc.LOGERROR)
        return False

def is_tv_in_trakt_watchlist(tvdb_id):
    headers = get_trakt_headers()
    if not headers:
        return False
    
    try:
        url = "https://api.trakt.tv/sync/watchlist/shows"
        resp = requests.get(url, headers=headers, timeout=15)
        if resp.status_code == 200:
            watchlist = resp.json()
            for item in watchlist:
                if item.get('show', {}).get('ids', {}).get('tvdb') == tvdb_id:
                    return True
    except Exception as e:
        log(f"Error checking TV watchlist: {e}", xbmc.LOGERROR)
    
    return False

def trakt_add_to_watchlist_simple(imdb_id=None, tvdb_id=None):
    headers = get_trakt_headers()
    if not headers:
        xbmcgui.Dialog().notification(ADDON_NAME, "Link Trakt first", xbmcgui.NOTIFICATION_ERROR)
        return False
    
    payload = {}
    
    if imdb_id:
        payload["movies"] = [{"ids": {"imdb": imdb_id}}]
    elif tvdb_id:
        payload["shows"] = [{"ids": {"tvdb": tvdb_id}}]
    else:
        return False
    
    url = "https://api.trakt.tv/sync/watchlist"
    try:
        resp = requests.post(url, headers=headers, json=payload, timeout=15)
        if resp.status_code in (200, 201):
            item_type = "movie" if imdb_id else "TV show"
            xbmcgui.Dialog().notification(ADDON_NAME, f"Added {item_type} to watchlist", xbmcgui.NOTIFICATION_INFO)
            return True
        else:
            log(f"Failed to add to watchlist: {resp.status_code} - {resp.text}", xbmc.LOGERROR)
            return False
    except Exception as e:
        log(f"Error adding to watchlist: {e}", xbmc.LOGERROR)
        return False

def trakt_remove_from_watchlist_simple(imdb_id=None, tvdb_id=None):
    headers = get_trakt_headers()
    if not headers:
        return False
    
    payload = {}
    
    if imdb_id:
        payload["movies"] = [{"ids": {"imdb": imdb_id}}]
    elif tvdb_id:
        payload["shows"] = [{"ids": {"tvdb": tvdb_id}}]
    else:
        return False
    
    url = "https://api.trakt.tv/sync/watchlist/remove"
    try:
        resp = requests.post(url, headers=headers, json=payload, timeout=15)
        if resp.status_code in (200, 201):
            log(f"Successfully removed item from watchlist", xbmc.LOGDEBUG)
            return True
        else:
            log(f"Failed to remove from watchlist: {resp.status_code} - {resp.text}", xbmc.LOGERROR)
            return False
    except Exception as e:
        log(f"Error removing from watchlist: {e}", xbmc.LOGERROR)
        return False

def trakt_mark_as_watched_simple(imdb_id):
    headers = get_trakt_headers()
    if not headers:
        return False
    
    payload = {"movies": [{"ids": {"imdb": imdb_id}}]}
    url = "https://api.trakt.tv/sync/history"
    try:
        resp = requests.post(url, headers=headers, json=payload, timeout=15)
        if resp.status_code in (200, 201):
            return True
        else:
            log(f"Failed to mark as watched: {resp.status_code} - {resp.text}", xbmc.LOGERROR)
            return False
    except Exception as e:
        log(f"Error marking as watched: {e}", xbmc.LOGERROR)
        return False

def is_in_trakt_watchlist(imdb_id):
    headers = get_trakt_headers()
    if not headers:
        return False
    
    try:
        url = "https://api.trakt.tv/sync/watchlist/movies"
        resp = requests.get(url, headers=headers, timeout=15)
        if resp.status_code == 200:
            watchlist = resp.json()
            for item in watchlist:
                if item.get('movie', {}).get('ids', {}).get('imdb') == imdb_id:
                    return True
    except Exception as e:
        log(f"Error checking watchlist: {e}", xbmc.LOGERROR)
    
    return False

def mark_watched_if_from_watchlist(imdb_id, from_watchlist):
    """Mark as watched if playing from watchlist"""
    if from_watchlist == "true":
        headers = get_trakt_headers()
        if not headers:
            log("No Trakt headers, skipping mark as watched", xbmc.LOGDEBUG)
            return
            
        if trakt_mark_as_watched_simple(imdb_id):
            log(f"Successfully marked {imdb_id} as watched", xbmc.LOGDEBUG)
        else:
            log(f"Failed to mark {imdb_id} as watched", xbmc.LOGDEBUG)

def enhanced_episode_details(tv_id, season_num, episode_num, show_title=""):
    handle = int(sys.argv[1])
    tmdb = TMDBClient()

    episode = tmdb.get_episode_details(tv_id, season_num, episode_num)
    if not episode:
        return

    title = episode.get("name", f"Episode {episode_num}")
    label = f"{show_title} - S{season_num}E{episode_num}: {title}"

    play_url = get_url(
        action="play_tv",
        tv_id=tv_id,
        season=season_num,
        episode=episode_num,
        title=label
    )
    play_subs_url = get_url(
        action="play_tv_subs",
        tv_id=tv_id,
        season=season_num,
        episode=episode_num,
        title=label,
        tmdb_id=episode.get("id")
    )

    item = xbmcgui.ListItem(label=label)
    still = build_image_url(episode.get("still_path"), "w500")
    fanart = build_image_url(episode.get("still_path"), BACKDROP_SIZE)
    item.setArt({
        'icon': still or 'DefaultVideo.png',
        'thumb': still or 'DefaultVideo.png',
        'fanart': fanart or ADDON_PATH + "/fanart.jpg"
    })
    item.setInfo('video', {
        'title': title,
        'plot': episode.get("overview", ""),
        'episode': episode_num,
        'season': season_num,
        'tvshowtitle': show_title
    })
    item.setProperty('IsPlayable', 'true')

    xbmcplugin.addDirectoryItem(handle, play_url, item, isFolder=False)

    play_subs_item = xbmcgui.ListItem(label=f"{label} with Subtitles")
    play_subs_item.setArt({'icon': 'DefaultVideo.png'})
    play_subs_item.setInfo('video', {'title': f"{label} with Subtitles"})
    play_subs_item.setProperty('IsPlayable', 'true')
    xbmcplugin.addDirectoryItem(handle, play_subs_url, play_subs_item, isFolder=False)

    xbmcplugin.setContent(handle, 'episodes')
    xbmcplugin.endOfDirectory(handle)

def play_tv_stream_with_subs(tv_id, season, episode, title, tmdb_id=None, from_watchlist="false"):
    tvdb_id = None
    try:
        if not tmdb_id:
            tmdb_id = tv_id
        tmdb_client = TMDBClient()
        tv_details = tmdb_client.get_tv_details(tmdb_id)
        if tv_details:
            tvdb_id = tv_details.get("external_ids", {}).get("tvdb_id")
    except Exception as e:
        log(f"Error getting TVDB ID: {e}", xbmc.LOGDEBUG)
        pass
    
    stream_url = get_tv_stream(tv_id, season, episode)
    
    if not stream_url:
        xbmcgui.Dialog().notification(ADDON_NAME, "TV stream not available", xbmcgui.NOTIFICATION_ERROR)
        return
    
    subtitle_path = None
    
    if tmdb_id:
        try:
            episode_details = tmdb_client.get_episode_details(tv_id, season, episode)
            if episode_details:
                episode_tmdb_id = episode_details.get("id")
                if episode_tmdb_id:
                    subtitles = get_subtitles(episode_tmdb_id, media_type="tv")
                    
                    if subtitles:
                        selected = show_subtitle_selector(subtitles)
                        
                        if selected and selected.get("url"):
                            subtitle_url = selected["url"]
                            sub_content = download_subtitle(subtitle_url)
                            
                            if sub_content:
                                temp_dir = xbmcvfs.translatePath("special://temp/")
                                sub_filename = f"sub_{episode_tmdb_id}_{int(time.time())}.srt"
                                subtitle_path = os.path.join(temp_dir, sub_filename)
                                
                                try:
                                    with open(subtitle_path, 'w', encoding='utf-8') as f:
                                        f.write(sub_content)
                                    log(f"Subtitles saved: {subtitle_path}")
                                except Exception as e:
                                    log(f"Failed to save subtitles: {str(e)}", xbmc.LOGERROR)
                                    subtitle_path = None
        except Exception as e:
            log(f"Error getting subtitles for TV: {e}", xbmc.LOGDEBUG)
    
    if not stream_url.startswith("https://"):
        stream_url = f"https://{stream_url}"
    
    log(f"Playing TV with subs: {stream_url[:100]}...")
    
    list_item = xbmcgui.ListItem(path=stream_url, label=title)
    list_item.setProperty('IsPlayable', 'true')
    list_item.setMimeType('application/vnd.apple.mpegurl')
    list_item.setContentLookup(False)
    
    list_item.setProperty('inputstream', 'inputstream.adaptive')
    list_item.setProperty('inputstream.adaptive.manifest_type', 'hls')
    list_item.setProperty('inputstream.adaptive.stream_headers', 
                         'User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
    
    if subtitle_path and os.pathexists(subtitle_path):
        list_item.setSubtitles([subtitle_path])
        log(f"Subtitles loaded from: {subtitle_path}")
    
    xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, list_item)

def enhanced_season_episodes(tv_id, season_num, show_title="", from_watchlist="false"):
    handle = int(sys.argv[1])
    tmdb = TMDBClient()

    season = tmdb.get_season_details(tv_id, season_num)

    if season and season.get("episodes"):
        for episode in season["episodes"]:
            ep_num = episode.get("episode_number", 1)
            title = episode.get("name", f"Episode {ep_num}")
            label = f"{ep_num}. {title}"
            
            episode_label = f"S{season_num}E{ep_num}: {title}"

            play_url = get_url(
                action="play_tv",
                tv_id=tv_id,
                season=season_num,
                episode=ep_num,
                title=f"{show_title} - {episode_label}",
                from_watchlist=from_watchlist
            )
            
            play_subs_url = get_url(
                action="play_tv_subs",
                tv_id=tv_id,
                season=season_num,
                episode=ep_num,
                title=f"{show_title} - {episode_label}",
                tmdb_id=tv_id,
                from_watchlist=from_watchlist
            )

            item = xbmcgui.ListItem(label=label)
            
            still = build_image_url(episode.get("still_path"), "w500")
            fanart = build_image_url(season.get("poster_path") or episode.get("still_path"), BACKDROP_SIZE)
            art = {
                'icon': still or 'DefaultVideo.png',
                'thumb': still or 'DefaultVideo.png',
                'fanart': fanart or ADDON_PATH + "/fanart.jpg"
            }
            item.setArt(art)

            info = {
                'title': title,
                'plot': episode.get("overview", ""),
                'episode': ep_num,
                'season': season_num,
                'tvshowtitle': show_title,
                'aired': episode.get("air_date", "")
            }
            item.setInfo('video', info)
            item.setProperty('IsPlayable', 'true')
            
            context_menu_items = [
                ("Play with Subtitles", f"PlayMedia({play_subs_url})")
            ]
            item.addContextMenuItems(context_menu_items)

            xbmcplugin.addDirectoryItem(handle, play_url, item, isFolder=False)

    xbmcplugin.setContent(handle, 'episodes')
    xbmcplugin.endOfDirectory(handle)

def enhanced_media_details(media_type, media_id):
    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    paid_user = is_paid_user()
    
    params = dict(urllib.parse.parse_qsl(sys.argv[2][1:]))
    from_watchlist = params.get("from_watchlist", "false")

    if media_type == "movie":
        media = tmdb.get_movie_details(media_id)
        if not media:
            return

        title = media.get("title", "Unknown")
        imdb_id = media.get("imdb_id", "")

        if not imdb_id:
            xbmcgui.Dialog().notification(ADDON_NAME, "No IMDB ID found", xbmcgui.NOTIFICATION_ERROR)
            return

        in_watchlist = False
        if paid_user:
            in_watchlist = is_in_trakt_watchlist(imdb_id)

        play_url = get_url(action="play_movie", ttid=imdb_id, title=title, from_watchlist=from_watchlist)
        play_item = xbmcgui.ListItem(label=f"Play {title}")
        play_item.setProperty('IsPlayable', 'true')
        play_item.setArt({'icon': 'DefaultVideo.png'})
        play_item.setInfo('video', {'title': f"Play {title}"})
        xbmcplugin.addDirectoryItem(handle, play_url, play_item, isFolder=False)

        play_subs_url = get_url(action="play_movie_subs", ttid=imdb_id, tmdb_id=media_id, title=title, from_watchlist=from_watchlist)
        play_subs_item = xbmcgui.ListItem(label=f"Play {title} with Subtitles")
        play_subs_item.setProperty('IsPlayable', 'true')
        play_subs_item.setArt({'icon': 'DefaultVideo.png'})
        play_subs_item.setInfo('video', {'title': f"Play {title} with Subtitles"})
        xbmcplugin.addDirectoryItem(handle, play_subs_url, play_subs_item, isFolder=False)

        if paid_user:
            if in_watchlist:
                remove_url = get_url(action="trakt_remove_watchlist", imdb_id=imdb_id)
                remove_item = xbmcgui.ListItem(label="Remove from Trakt Watchlist")
                remove_item.setArt({'icon': 'DefaultVideo.png'})
                remove_item.setInfo('video', {'title': "Remove from Trakt Watchlist"})
                xbmcplugin.addDirectoryItem(handle, remove_url, remove_item, isFolder=False)
            else:
                add_url = get_url(action="trakt_add_watchlist", imdb_id=imdb_id)
                add_item = xbmcgui.ListItem(label="Add to Trakt Watchlist")
                add_item.setArt({'icon': 'DefaultVideo.png'})
                add_item.setInfo('video', {'title': "Add to Trakt Watchlist"})
                xbmcplugin.addDirectoryItem(handle, add_url, add_item, isFolder=False)

    elif media_type == "tv":
        media = tmdb.get_tv_details(media_id)
        if not media:
            return

        show_title = media.get("name", "TV Show")
        
        external_ids = media.get("external_ids", {})
        tvdb_id = external_ids.get("tvdb_id")
        
        in_watchlist = False
        if paid_user and tvdb_id:
            in_watchlist = is_tv_in_trakt_watchlist(tvdb_id)

        if paid_user and tvdb_id:
            if in_watchlist:
                remove_url = get_url(action="trakt_remove_tv_watchlist", tvdb_id=tvdb_id)
                remove_item = xbmcgui.ListItem(label="Remove from Trakt Watchlist")
                remove_item.setArt({'icon': 'DefaultVideo.png'})
                remove_item.setInfo('video', {'title': "Remove from Trakt Watchlist"})
                xbmcplugin.addDirectoryItem(handle, remove_url, remove_item, isFolder=False)
            else:
                add_url = get_url(action="trakt_add_tv_watchlist", tvdb_id=tvdb_id)
                add_item = xbmcgui.ListItem(label="Add to Trakt Watchlist")
                add_item.setArt({'icon': 'DefaultVideo.png'})
                add_item.setInfo('video', {'title': "Add to Trakt Watchlist"})
                xbmcplugin.addDirectoryItem(handle, add_url, add_item, isFolder=False)

        if media.get("seasons"):
            for season in media["seasons"]:
                season_num = season.get("season_number", 0)
                if season_num == 0:
                    continue

                season_name = season.get("name", f"Season {season_num}")
                label = season_name
                
                episode_count = season.get("episode_count", 0)
                if episode_count > 0:
                    label = f"{label} ({episode_count} episodes)"
                
                url = get_url(action="season_episodes", id=media_id, season=season_num, show_title=show_title, from_watchlist=from_watchlist)
                item = xbmcgui.ListItem(label=label)

                poster = build_image_url(season.get("poster_path"), POSTER_SIZE)
                fanart = build_image_url(media.get("backdrop_path"), BACKDROP_SIZE)
                
                item.setArt({
                    'icon': poster or 'DefaultFolder.png', 
                    'thumb': poster or 'DefaultFolder.png', 
                    'fanart': fanart or ADDON_PATH + "/fanart.jpg"
                })
                
                item.setInfo('video', {
                    'title': season_name,
                    'tvshowtitle': show_title,
                    'plot': season.get("overview", media.get("overview", "")),
                    'season': season_num
                })
                
                xbmcplugin.addDirectoryItem(handle, url, item, isFolder=True)

    xbmcplugin.setContent(handle, 'movies' if media_type=="movie" else 'tvshows')
    xbmcplugin.endOfDirectory(handle)

def get_client_id():
    if xbmcvfs.exists(CLIENT_ID_FILE):
        try:
            with xbmcvfs.File(CLIENT_ID_FILE, 'r') as f:
                client_id = f.read().strip()
                if client_id:
                    return client_id
        except Exception as e:
            log(f"Error reading client ID: {e}", xbmc.LOGDEBUG)
    
    client_id = str(uuid.uuid4())
    
    try:
        folder = xbmcvfs.translatePath(f"special://profile/addon_data/{ADDON_ID}")
        if not xbmcvfs.exists(folder):
            xbmcvfs.mkdirs(folder)
            log(f"Created folder: {folder}", xbmc.LOGDEBUG)
        
        with xbmcvfs.File(CLIENT_ID_FILE, 'w') as f:
            f.write(client_id)
        log(f"Generated new client ID: {client_id}", xbmc.LOGDEBUG)
        
    except Exception as e:
        log(f"Failed to save client ID: {str(e)}", xbmc.LOGERROR)
        return "fallback-" + str(uuid.uuid4())[:8]
    
    return client_id

def log(msg, level=xbmc.LOGINFO):
    xbmc.log(f"[{ADDON_ID}] {msg}", level)

def get_url(**kwargs):
    return f"plugin://{ADDON_ID}?{urllib.parse.urlencode(kwargs)}"

def make_request(url, params=None, timeout=10):
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Accept': 'application/json'
        }
        response = requests.get(url, params=params, headers=headers, timeout=timeout)
        response.raise_for_status()
        return response.json()
    except Exception as e:
        log(f"Request failed: {url} - Error: {str(e)}", xbmc.LOGERROR)
        return None

class TMDBClient:
    
    def __init__(self):
        self.api_key = TMDB_API_KEY
        self.base_params = {"api_key": self.api_key, "language": "en-US"}
    
    def get_movie_genres(self):
        url = f"{TMDB_BASE_URL}/genre/movie/list"
        data = make_request(url, self.base_params)
        return data.get("genres", []) if data else []
    
    def get_tv_genres(self):
        url = f"{TMDB_BASE_URL}/genre/tv/list"
        data = make_request(url, self.base_params)
        return data.get("genres", []) if data else []
    
    def get_popular_movies(self, page=1):
        url = f"{TMDB_BASE_URL}/movie/popular"
        params = {**self.base_params, "page": page}
        return make_request(url, params)
    
    def get_top_rated_movies(self, page=1):
        url = f"{TMDB_BASE_URL}/movie/top_rated"
        params = {**self.base_params, "page": page}
        return make_request(url, params)
    
    def get_now_playing_movies(self, page=1):
        url = f"{TMDB_BASE_URL}/movie/now_playing"
        params = {**self.base_params, "page": page}
        return make_request(url, params)
    
    def get_upcoming_movies(self, page=1):
        url = f"{TMDB_BASE_URL}/movie/upcoming"
        params = {**self.base_params, "page": page}
        return make_request(url, params)
    
    def get_popular_tv(self, page=1):
        url = f"{TMDB_BASE_URL}/tv/popular"
        params = {**self.base_params, "page": page}
        return make_request(url, params)
    
    def get_top_rated_tv(self, page=1):
        url = f"{TMDB_BASE_URL}/tv/top_rated"
        params = {**self.base_params, "page": page}
        return make_request(url, params)
    
    def get_tv_on_air(self, page=1):
        url = f"{TMDB_BASE_URL}/tv/on_the_air"
        params = {**self.base_params, "page": page}
        return make_request(url, params)
    
    def get_movies_by_genre(self, genre_id, page=1):
        url = f"{TMDB_BASE_URL}/discover/movie"
        params = {
            **self.base_params,
            "with_genres": genre_id,
            "sort_by": "popularity.desc",
            "page": page
        }
        return make_request(url, params)
    
    def get_tv_by_genre(self, genre_id, page=1):
        url = f"{TMDB_BASE_URL}/discover/tv"
        params = {
            **self.base_params,
            "with_genres": genre_id,
            "sort_by": "popularity.desc",
            "page": page
        }
        return make_request(url, params)
    
    def search_movies(self, query, page=1):
        url = f"{TMDB_BASE_URL}/search/movie"
        params = {**self.base_params, "query": query, "page": page}
        return make_request(url, params)
    
    def search_tv(self, query, page=1):
        url = f"{TMDB_BASE_URL}/search/tv"
        params = {**self.base_params, "query": query, "page": page}
        return make_request(url, params)
    
    def get_movie_details(self, movie_id):
        url = f"{TMDB_BASE_URL}/movie/{movie_id}"
        params = {**self.base_params, "append_to_response": "credits,external_ids"}
        return make_request(url, params)
    
    def get_tv_details(self, tv_id):
        url = f"{TMDB_BASE_URL}/tv/{tv_id}"
        params = {**self.base_params, "append_to_response": "credits,seasons,external_ids"}
        return make_request(url, params)
    
    def get_season_details(self, tv_id, season_number):
        url = f"{TMDB_BASE_URL}/tv/{tv_id}/season/{season_number}"
        return make_request(url, self.base_params)
    
    def get_episode_details(self, tv_id, season_number, episode_number):
        url = f"{TMDB_BASE_URL}/tv/{tv_id}/season/{season_number}/episode/{episode_number}"
        params = {**self.base_params, "append_to_response": "external_ids"}
        return make_request(url, params)
    
    def get_trending_movies(self, page=1):
        url = f"{TMDB_BASE_URL}/trending/movie/week"
        params = {**self.base_params, "page": page}
        return make_request(url, params)

    def get_trending_tv(self, page=1):
        url = f"{TMDB_BASE_URL}/trending/tv/week"
        params = {**self.base_params, "page": page}
        return make_request(url, params)

    def get_tv_airing_today(self, page=1):
        url = f"{TMDB_BASE_URL}/tv/airing_today"
        params = {**self.base_params, "page": page}
        return make_request(url, params)

def get_stream_url(ttid, retry=True):
    user_api_key = ADDON.getSetting("paid_api_key")
    if user_api_key:
        user_api_key = user_api_key.strip()
    
    if user_api_key:
        api_key = user_api_key
        log(f"Using user-provided API Key: {api_key[:8]}...", xbmc.LOGDEBUG)
    else:
        api_key = "FREE-ABC-123"
        log(f"No user API key, using free key", xbmc.LOGDEBUG)
    
    client_id = get_client_id()
    
    headers = {
        "X-API-Key": api_key,
        "X-Client-ID": client_id,
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
        "Accept": "application/json"
    }

    try:
        log(f"Client ID: {client_id}", xbmc.LOGDEBUG)
        log(f"Requesting stream for: {ttid}", xbmc.LOGDEBUG)
        
        response = requests.get(
            STREAM_API_URL,
            headers=headers,
            params={"d": ttid},
            timeout=30
        )

        log(f"Stream API response ({response.status_code}): {response.text[:500]}...", xbmc.LOGDEBUG)

        if response.status_code == 200:
            data = response.json()
            stream_url = data.get("data", {}).get("stream_info", {}).get("url")
            if stream_url:
                log(f"Got stream URL: {stream_url[:100]}...", xbmc.LOGDEBUG)
                
                if user_api_key and user_api_key != "FREE-ABC-123":
                    is_paid_user(force_refresh=True)
                    
                return stream_url
            else:
                log(f"No stream URL found in response", xbmc.LOGWARNING)
                return None
        
        if response.status_code == 429:
            detail = "Rate limited"
            try:
                detail = response.json().get("detail", detail)
            except:
                pass
            retry_after = response.headers.get("Retry-After")
            if retry_after:
                detail += f" - try again in {retry_after} seconds"
            xbmcgui.Dialog().notification(ADDON_NAME, detail, xbmcgui.NOTIFICATION_ERROR)
            return None
            
        elif response.status_code in (401, 400):
            error_msg = "API key or client ID rejected"
            try:
                error_data = response.json()
                error_msg = error_data.get("detail", error_msg)
            except:
                pass
            
            if user_api_key and user_api_key != "FREE-ABC-123":
                log(f"User API key rejected: {error_msg}", xbmc.LOGERROR)
                if xbmcvfs.exists(PAID_CACHE_FILE):
                    xbmcvfs.delete(PAID_CACHE_FILE)
                    log("Cleared paid cache due to invalid API key", xbmc.LOGDEBUG)
            
            xbmcgui.Dialog().notification(ADDON_NAME, error_msg, xbmcgui.NOTIFICATION_ERROR)
            return None
            
        else:
            log(f"Unexpected API status {response.status_code}: {response.text[:200]}", xbmc.LOGERROR)
            xbmcgui.Dialog().notification(ADDON_NAME, f"API error: {response.status_code}", xbmcgui.NOTIFICATION_ERROR)
            return None

    except requests.exceptions.Timeout:
        log("Stream API timeout", xbmc.LOGERROR)
        xbmcgui.Dialog().notification(ADDON_NAME, "Connection timeout", xbmcgui.NOTIFICATION_ERROR)
        return None
        
    except Exception as e:
        log(f"Stream API error: {e}", xbmc.LOGERROR)
        xbmcgui.Dialog().notification(ADDON_NAME, "Stream error", xbmc.LOGERROR)
        return None

def get_tv_stream(tv_id, season, episode):
    try:
        tv_format = f"tv/{tv_id}/{season}/{episode}"
        log(f"Getting TV stream for: {tv_format}", xbmc.LOGDEBUG)
        return get_stream_url(tv_format)
    except Exception as e:
        log(f"TV Stream API error: {str(e)}", xbmc.LOGERROR)
    return None

def get_subtitles(tmdb_id, media_type="movie"):
    try:
        if media_type == "movie":
            url = f"{SUBTITLE_API_URL}?id={tmdb_id}&format=srt"
        else:
            url = f"{SUBTITLE_API_URL}?imdb={tmdb_id}&format=srt"
        
        response = requests.get(url, timeout=10)
        
        if response.status_code == 200:
            return response.json()
    except Exception as e:
        log(f"Subtitle error: {str(e)}", xbmc.LOGERROR)
    
    return []

def download_subtitle(subtitle_url):
    try:
        response = requests.get(subtitle_url, timeout=10)
        if response.status_code == 200:
            return response.text
    except Exception as e:
        log(f"Subtitle download error: {str(e)}", xbmc.LOGERROR)
    
    return ""

def show_subtitle_selector(subtitles_data):
    if not subtitles_data:
        return None
    
    items = []
    subtitle_items = []
    
    for sub in subtitles_data:
        language = sub.get("display", sub.get("language", "Unknown"))
        format_type = sub.get("format", "srt").upper()
        source = sub.get("source", "")
        
        label = f"{language} ({format_type})"
        if source:
            label += f" - {source}"
        
        items.append(label)
        subtitle_items.append(sub)

    items.append("No subtitles")
    
    dialog = xbmcgui.Dialog()
    choice = dialog.select("Select Subtitles", items)
    
    if choice >= 0 and choice < len(subtitle_items):
        return subtitle_items[choice]
    
    return None

def play_stream(ttid, title, from_watchlist="false"):
    """Play stream WITHOUT subtitles"""
    # Remove from watchlist immediately if playing from watchlist
    if from_watchlist == "true":
        log(f"Attempting to remove {ttid} from watchlist", xbmc.LOGDEBUG)
        # JUST remove from watchlist, don't call mark_watched_if_from_watchlist
        trakt_remove_from_watchlist_simple(imdb_id=ttid)
    
    stream_url = get_stream_url(ttid)
    
    if not stream_url:
        xbmcgui.Dialog().notification(ADDON_NAME, "Stream not available", xbmcgui.NOTIFICATION_ERROR)
        return
    
    if not stream_url.startswith("https://"):
        stream_url = f"https://{stream_url}"
    
    log(f"Playing (no subs): {stream_url[:100]}...")
    
    list_item = xbmcgui.ListItem(path=stream_url, label=title)
    list_item.setProperty('IsPlayable', 'true')
    list_item.setMimeType('application/vnd.apple.mpegurl')
    list_item.setContentLookup(False)

    list_item.setProperty('inputstream', 'inputstream.adaptive')
    list_item.setProperty('inputstream.adaptive.manifest_type', 'hls')
    list_item.setProperty('inputstream.adaptive.stream_headers', 
                         'User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
    
    xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, list_item)

def play_tv_stream(tv_id, season, episode, title, from_watchlist="false"):
    stream_url = get_tv_stream(tv_id, season, episode)
    
    if not stream_url:
        xbmcgui.Dialog().notification(ADDON_NAME, "TV stream not available", xbmcgui.NOTIFICATION_ERROR)
        return
    
    if not stream_url.startswith("https://"):
        stream_url = f"https://{stream_url}"
    
    log(f"Playing TV: {stream_url[:100]}...")
    
    list_item = xbmcgui.ListItem(path=stream_url, label=title)
    list_item.setProperty('IsPlayable', 'true')
    list_item.setMimeType('application/vnd.apple.mpegurl')
    list_item.setContentLookup(False)
    
    list_item.setProperty('inputstream', 'inputstream.adaptive')
    list_item.setProperty('inputstream.adaptive.manifest_type', 'hls')
    list_item.setProperty('inputstream.adaptive.stream_headers', 
                         'User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
    
    xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, list_item)

def play_stream_with_subs(ttid, title, tmdb_id=None, media_type="movie", from_watchlist="false"):
    """Play stream WITH subtitle support"""
    # Remove from watchlist immediately if playing from watchlist
    if from_watchlist == "true" and media_type == "movie":
        log(f"Attempting to remove {ttid} from watchlist (with subs)", xbmc.LOGDEBUG)
        # JUST remove from watchlist, don't call mark_watched_if_from_watchlist
        trakt_remove_from_watchlist_simple(imdb_id=ttid)
    
    stream_url = get_stream_url(ttid)
    
    if not stream_url:
        xbmcgui.Dialog().notification(ADDON_NAME, "Stream not available", xbmcgui.NOTIFICATION_ERROR)
        return
    
    subtitle_path = None
    
    if tmdb_id:
        subtitles = get_subtitles(tmdb_id, media_type)
        
        if subtitles:
            selected = show_subtitle_selector(subtitles)
            
            if selected and selected.get("url"):
                subtitle_url = selected["url"]
                
                sub_content = download_subtitle(subtitle_url)
                
                if sub_content:
                    temp_dir = xbmcvfs.translatePath("special://temp/")
                    sub_filename = f"sub_{tmdb_id}_{int(time.time())}.srt"
                    subtitle_path = os.path.join(temp_dir, sub_filename)
                    
                    try:
                        with open(subtitle_path, 'w', encoding='utf-8') as f:
                            f.write(sub_content)
                        log(f"Subtitles saved: {subtitle_path}")
                    except Exception as e:
                        log(f"Failed to save subtitles: {str(e)}", xbmc.LOGERROR)
                        subtitle_path = None
    
    if not stream_url.startswith("https://"):
        stream_url = f"https://{stream_url}"
    
    log(f"Playing: {stream_url[:100]}...")
    
    list_item = xbmcgui.ListItem(path=stream_url, label=title)
    list_item.setProperty('IsPlayable', 'true')
    list_item.setMimeType('application/vnd.apple.mpegurl')
    list_item.setContentLookup(False)
    
    list_item.setProperty('inputstream', 'inputstream.adaptive')
    list_item.setProperty('inputstream.adaptive.manifest_type', 'hls')
    list_item.setProperty('inputstream.adaptive.stream_headers', 
                         'User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
    
    if subtitle_path and os.path.exists(subtitle_path):
        list_item.setSubtitles([subtitle_path])
        log(f"Subtitles loaded from: {subtitle_path}")
    
    xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, list_item)

def build_image_url(path, size="w500"):
    if not path:
        return ""
    return f"{IMAGE_BASE_URL}{size}{path}"

def link_trakt_account():
    show_trakt_url_simple()

def show_trakt_url_simple():
    trakt_url = "https://shorturl.at/hfp6R"
    
    xbmcgui.Dialog().textviewer(
        "Link Trakt Account",
        f"OPEN THIS LINK ON YOUR PHONE:\n\n"
        f"{trakt_url}\n\n"
        "EASY STEPS:\n"
        "1. Take a PHOTO of this screen\n"
        "2. Open the photo on your phone\n"
        "3. Tap the URL in the photo\n"
        "4. Authorize on Trakt\n"
        "5. Copy the code\n"
        "6. Come back here to enter it\n\n"
        "Click OK when ready to enter code"
    )
    
    get_trakt_code_simple()

def process_trakt_code(code):
    progress = xbmcgui.DialogProgress()
    progress.create(ADDON_NAME, "Linking Trakt account...")
    
    try:
        progress.update(25, "Validating code...")
        
        token_data = exchange_trakt_code(code)
        
        progress.update(100)
        progress.close()
        
        if token_data:
            username = token_data.get('username', 'N/A')
            ADDON.setSetting("trakt_username", username)
            
            xbmcgui.Dialog().ok(
                "Trakt Account Linked!",
                f"Successfully linked to:\n\n"
                f"{username}\n\n"
                "You can now access your Trakt watchlist."
            )
            
            xbmc.executebuiltin("Container.Refresh")
            
        else:
            xbmcgui.Dialog().ok(
                "Linking Failed",
                "Could not link Trakt account.\n\n"
                "Possible reasons:\n"
                "Code expired (get a new one)\n"
                "Network connection issue\n"
                "Invalid authorization code\n\n"
                "Try again with a fresh code from Trakt.tv"
            )
            
    except Exception as e:
        if progress:
            progress.close()
        
        log(f"Trakt linking error: {e}", xbmc.LOGERROR)
        xbmcgui.Dialog().ok(
            "Error",
            f"Trakt linking failed:\n\n{str(e)[:200]}"
        )

def get_trakt_code_simple():
    keyboard = xbmc.Keyboard()
    keyboard.setHeading("Enter Trakt Authorization Code")
    keyboard.doModal()
    
    if keyboard.isConfirmed():
        code = keyboard.getText()
        if code:
            process_trakt_code(code)
        else:
            xbmcgui.Dialog().notification(ADDON_NAME, "No code entered", xbmcgui.NOTIFICATION_WARNING)

def main_menu():
    handle = int(sys.argv[1])

    li = xbmcgui.ListItem("Movies")
    url = get_url(action="movies")
    xbmcplugin.addDirectoryItem(handle, url, li, isFolder=True)

    li = xbmcgui.ListItem("TV Shows")
    url = get_url(action="tv_shows")
    xbmcplugin.addDirectoryItem(handle, url, li, isFolder=True)

    li = xbmcgui.ListItem("Search")
    url = get_url(action="search")
    xbmcplugin.addDirectoryItem(handle, url, li, isFolder=True)

    if is_paid_user():
        headers = get_trakt_headers()
        if headers:
            li = xbmcgui.ListItem("Trakt Watchlist")
            url = get_url(action="trakt_watchlist")
        else:
            li = xbmcgui.ListItem("Link Trakt Account")
            url = get_url(action="trakt_link")  
        li.setArt({'icon': 'DefaultFolder.png', 'thumb': 'DefaultFolder.png'})
        li.setInfo('video', {'title': li.getLabel()})
        xbmcplugin.addDirectoryItem(handle, url, li, isFolder=True)

    xbmcplugin.endOfDirectory(handle)

def movies_menu():
    handle = int(sys.argv[1])
    
    categories = [
        ("Popular", "movie_popular"),
        ("Top Rated", "movie_top_rated"),
        ("Now Playing", "movie_now_playing"),
        ("Upcoming", "movie_upcoming"),
        ("Trending", "movie_trending"),  
        ("Genres", "movie_genres")
    ]
    
    for label, action in categories:
        url = get_url(action=action)
        list_item = xbmcgui.ListItem(label=label)
        list_item.setArt({'icon': 'DefaultFolder.png', 'thumb': 'DefaultFolder.png'})
        list_item.setInfo('video', {'title': label})
        xbmcplugin.addDirectoryItem(handle, url, list_item, isFolder=True)
    
    xbmcplugin.setContent(handle, 'files')
    xbmcplugin.endOfDirectory(handle)

def tv_shows_menu():
    handle = int(sys.argv[1])
    
    categories = [
        ("Popular", "tv_popular"),
        ("Top Rated", "tv_top_rated"),
        ("On Air", "tv_on_air"),
        ("Airing Today", "tv_airing_today"),  
        ("Trending", "tv_trending"),          
        ("Genres", "tv_genres")
    ]
    
    for label, action in categories:
        url = get_url(action=action)
        list_item = xbmcgui.ListItem(label=label)
        list_item.setArt({'icon': 'DefaultFolder.png', 'thumb': 'DefaultFolder.png'})
        list_item.setInfo('video', {'title': label})
        xbmcplugin.addDirectoryItem(handle, url, list_item, isFolder=True)
    
    xbmcplugin.setContent(handle, 'files')
    xbmcplugin.endOfDirectory(handle)

def list_movies(action, page=1):
    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    
    action_map = {
        "movie_popular": tmdb.get_popular_movies,
        "movie_top_rated": tmdb.get_top_rated_movies,
        "movie_now_playing": tmdb.get_now_playing_movies,
        "movie_upcoming": tmdb.get_upcoming_movies,
        "movie_trending": tmdb.get_trending_movies  
    }
    
    if action in action_map:
        data = action_map[action](page)
        if data and data.get("results"):
            for movie in data["results"]:
                title = movie.get("title", "Unknown")
                year = movie.get("release_date", "")[:4] if movie.get("release_date") else ""
                label = f"{title} ({year})" if year else title
                url = get_url(action="movie_details", id=movie["id"])
                
                list_item = xbmcgui.ListItem(label=label)
                poster = build_image_url(movie.get("poster_path"), POSTER_SIZE)
                fanart = build_image_url(movie.get("backdrop_path"), BACKDROP_SIZE)
                art = {'icon': poster, 'thumb': poster, 'poster': poster, 'fanart': fanart or ADDON_PATH + "/fanart.jpg"}
                list_item.setArt(art)
                
                info = {'title': title, 'year': int(year) if year.isdigit() else 0,
                        'plot': movie.get("overview", ""), 'rating': float(movie.get("vote_average", 0))}
                list_item.setInfo('video', info)
                
                xbmcplugin.addDirectoryItem(handle, url, list_item, isFolder=True)
            
            if data.get("total_pages", 0) > page:
                next_url = get_url(action=action, page=page + 1)
                next_item = xbmcgui.ListItem(label="Next Page")
                next_item.setArt({'icon': 'DefaultFolder.png'})
                xbmcplugin.addDirectoryItem(handle, next_url, next_item, isFolder=True)
    
    xbmcplugin.setContent(handle, 'movies')
    xbmcplugin.endOfDirectory(handle)

def list_tv_shows(action, page=1):
    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    
    action_map = {
        "tv_popular": tmdb.get_popular_tv,
        "tv_top_rated": tmdb.get_top_rated_tv,
        "tv_on_air": tmdb.get_tv_on_air,
        "tv_airing_today": tmdb.get_tv_airing_today,  
        "tv_trending": tmdb.get_trending_tv         
    }
    
    if action in action_map:
        data = action_map[action](page)
        if data and data.get("results"):
            for tv in data["results"]:
                title = tv.get("name", "Unknown")
                year = tv.get("first_air_date", "")[:4] if tv.get("first_air_date") else ""
                label = f"{title} ({year})" if year else title
                url = get_url(action="tv_details", id=tv["id"])
                
                list_item = xbmcgui.ListItem(label=label)
                poster = build_image_url(tv.get("poster_path"), POSTER_SIZE)
                fanart = build_image_url(tv.get("backdrop_path"), BACKDROP_SIZE)
                art = {'icon': poster, 'thumb': poster, 'poster': poster, 'fanart': fanart or ADDON_PATH + "/fanart.jpg"}
                list_item.setArt(art)
                
                info = {'title': title, 'year': int(year) if year.isdigit() else 0,
                        'plot': tv.get("overview", ""), 'rating': float(tv.get("vote_average", 0))}
                list_item.setInfo('video', info)
                
                xbmcplugin.addDirectoryItem(handle, url, list_item, isFolder=True)
            
            if data.get("total_pages", 0) > page:
                next_url = get_url(action=action, page=page + 1)
                next_item = xbmcgui.ListItem(label="Next Page")
                next_item.setArt({'icon': 'DefaultFolder.png'})
                xbmcplugin.addDirectoryItem(handle, next_url, next_item, isFolder=True)
    
    xbmcplugin.setContent(handle, 'tvshows')
    xbmcplugin.endOfDirectory(handle)

def movie_genres():
    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    
    genres = tmdb.get_movie_genres()
    
    for genre in genres:
        url = get_url(action="movie_genre", id=genre["id"], name=genre["name"])
        list_item = xbmcgui.ListItem(label=genre["name"])
        list_item.setArt({'icon': 'DefaultFolder.png'})
        list_item.setInfo('video', {'title': genre["name"]})
        xbmcplugin.addDirectoryItem(handle, url, list_item, isFolder=True)
    
    xbmcplugin.setContent(handle, 'files')
    xbmcplugin.endOfDirectory(handle)

def tv_genres():
    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    
    genres = tmdb.get_tv_genres()
    
    for genre in genres:
        url = get_url(action="tv_genre", id=genre["id"], name=genre["name"])
        list_item = xbmcgui.ListItem(label=genre["name"])
        list_item.setArt({'icon': 'DefaultFolder.png'})
        list_item.setInfo('video', {'title': genre["name"]})
        xbmcplugin.addDirectoryItem(handle, url, list_item, isFolder=True)
    
    xbmcplugin.setContent(handle, 'files')
    xbmcplugin.endOfDirectory(handle)

def movies_by_genre(genre_id, page=1, genre_name=""):
    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    
    data = tmdb.get_movies_by_genre(genre_id, page)
    
    xbmcplugin.setPluginCategory(handle, f"Movies - {genre_name}" if genre_name else "Movies")
    
    if data and data.get("results"):
        for movie in data["results"]:
            title = movie.get("title", "Unknown")
            year = movie.get("release_date", "")[:4] if movie.get("release_date") else ""
            label = f"{title} ({year})" if year else title
            
            url = get_url(action="movie_details", id=movie["id"])
            list_item = xbmcgui.ListItem(label=label)
            
            poster = build_image_url(movie.get("poster_path"), POSTER_SIZE)
            fanart = build_image_url(movie.get("backdrop_path"), BACKDROP_SIZE)
            
            art = {
                'icon': poster,
                'thumb': poster,
                'poster': poster,
                'fanart': fanart or ADDON_PATH + "/fanart.jpg"
            }
            list_item.setArt(art)
            
            info = {
                'title': title,
                'year': int(year) if year.isdigit() else 0,
                'plot': movie.get("overview", ""),
                'rating': float(movie.get("vote_average", 0))
            }
            list_item.setInfo('video', info)
            
            xbmcplugin.addDirectoryItem(handle, url, list_item, isFolder=True)
        
        total_pages = data.get("total_pages", 0)
        
        if total_pages > page:
            next_url = get_url(action="movie_genre", id=genre_id, page=page + 1, name=genre_name)
            next_item = xbmcgui.ListItem(label=f"Page {page + 1} of {total_pages}")
            next_item.setArt({'icon': 'DefaultFolder.png'})
            next_item.setInfo('video', {'title': f"Next Page ({page + 1}/{total_pages})"})
            xbmcplugin.addDirectoryItem(handle, next_url, next_item, isFolder=True)
    
    xbmcplugin.setContent(handle, 'movies')
    xbmcplugin.endOfDirectory(handle)

def tv_by_genre(genre_id, page=1, genre_name=""):
    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    
    data = tmdb.get_tv_by_genre(genre_id, page)
    
    xbmcplugin.setPluginCategory(handle, f"TV Shows - {genre_name}" if genre_name else "TV Shows")
    
    if data and data.get("results"):
        for tv in data["results"]:
            title = tv.get("name", "Unknown")
            year = tv.get("first_air_date", "")[:4] if tv.get("first_air_date") else ""
            label = f"{title} ({year})" if year else title
            
            url = get_url(action="tv_details", id=tv["id"])
            list_item = xbmcgui.ListItem(label=label)
            
            poster = build_image_url(tv.get("poster_path"), POSTER_SIZE)
            fanart = build_image_url(tv.get("backdrop_path"), BACKDROP_SIZE)
            
            art = {
                'icon': poster,
                'thumb': poster,
                'poster': poster,
                'fanart': fanart or ADDON_PATH + "/fanart.jpg"
            }
            list_item.setArt(art)
            
            info = {
                'title': title,
                'year': int(year) if year.isdigit() else 0,
                'plot': tv.get("overview", ""),
                'rating': float(tv.get("vote_average", 0))
            }
            list_item.setInfo('video', info)
            
            xbmcplugin.addDirectoryItem(handle, url, list_item, isFolder=True)
        
        total_pages = data.get("total_pages", 0)
        
        if total_pages > page:
            next_url = get_url(action="tv_genre", id=genre_id, page=page + 1, name=genre_name)
            next_item = xbmcgui.ListItem(label=f"Page {page + 1} of {total_pages}")
            next_item.setArt({'icon': 'DefaultFolder.png'})
            next_item.setInfo('video', {'title': f"Next Page ({page + 1}/{total_pages})"})
            xbmcplugin.addDirectoryItem(handle, next_url, next_item, isFolder=True)
    
    xbmcplugin.setContent(handle, 'tvshows')
    xbmcplugin.endOfDirectory(handle)

def season_episodes(tv_id, season_num, show_title=""):
    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    
    season = tmdb.get_season_details(tv_id, season_num)
    
    if season and season.get("episodes"):
        for episode in season["episodes"]:
            ep_num = episode.get("episode_number", 1)
            title = episode.get("name", f"Episode {ep_num}")
            label = f"{ep_num}. {title}"
            
            play_url = get_url(
                action="play_tv", 
                tv_id=tv_id,
                season=season_num,
                episode=ep_num,
                title=f"{show_title} - S{season_num}E{ep_num}: {title}"
            )
            
            item = xbmcgui.ListItem(label=label)
            
            still = build_image_url(episode.get("still_path"), "w500")
            fanart = build_image_url(season.get("poster_path") or episode.get("still_path"), BACKDROP_SIZE)
            
            art = {
                'icon': still or 'DefaultVideo.png',
                'thumb': still or 'DefaultVideo.png',
                'fanart': fanart or ADDON_PATH + "/fanart.jpg"
            }
            item.setArt(art)
            
            info = {
                'title': title,
                'plot': episode.get("overview", ""),
                'episode': ep_num,
                'season': season_num,
                'tvshowtitle': show_title,
                'aired': episode.get("air_date", "")
            }
            item.setInfo('video', info)
            item.setProperty('IsPlayable', 'true')
            
            xbmcplugin.addDirectoryItem(handle, play_url, item, isFolder=False)
    
    xbmcplugin.setContent(handle, 'episodes')
    xbmcplugin.endOfDirectory(handle)

def search_menu():
    keyboard_search()

def keyboard_search():
    keyboard = xbmc.Keyboard()
    keyboard.setHeading("Search for movies or TV shows")
    keyboard.doModal()
    
    if keyboard.isConfirmed():
        query = keyboard.getText()
        if query:
            dialog = xbmcgui.Dialog()
            choice = dialog.select("Search in:", ["Movies", "TV Shows"])
            
            if choice == 0:
                perform_search(query, "movie")
            elif choice == 1:
                perform_search(query, "tv")

def perform_search(query, search_type, page=1):
    handle = int(sys.argv[1])
    tmdb = TMDBClient()
    
    if search_type == "movie":
        data = tmdb.search_movies(query, page)
        item_type = "movies"
    else:
        data = tmdb.search_tv(query, page)
        item_type = "tvshows"
    
    if data and data.get("results"):
        for item in data["results"]:
            if search_type == "movie":
                title = item.get("title", "Unknown")
                year = item.get("release_date", "")[:4] if item.get("release_date") else ""
                label = f"{title} ({year})" if year else title
                action = "movie_details"
                poster_path = item.get("poster_path")
            else:
                title = item.get("name", "Unknown")
                year = item.get("first_air_date", "")[:4] if item.get("first_air_date") else ""
                label = f"{title} ({year})" if year else title
                action = "tv_details"
                poster_path = item.get("poster_path")
            
            url = get_url(action=action, id=item["id"])
            list_item = xbmcgui.ListItem(label=label)
            
            poster = build_image_url(poster_path, POSTER_SIZE)
            fanart = build_image_url(item.get("backdrop_path"), BACKDROP_SIZE)
            
            art = {
                'icon': poster,
                'thumb': poster,
                'poster': poster,
                'fanart': fanart or ADDON_PATH + "/fanart.jpg"
            }
            list_item.setArt(art)
            
            info = {
                'title': title,
                'year': int(year) if year.isdigit() else 0,
                'plot': item.get("overview", ""),
                'rating': float(item.get("vote_average", 0))
            }
            list_item.setInfo('video', info)
            
            xbmcplugin.addDirectoryItem(handle, url, list_item, isFolder=True)
    
    xbmcplugin.setContent(handle, item_type)
    xbmcplugin.endOfDirectory(handle)

def router(paramstring):
    params = dict(urllib.parse.parse_qsl(paramstring))
    
    action = params.get("action", "main")
    page = int(params.get("page", 1))
    
    if action == "main":
        main_menu()
    elif action == "movies":
        movies_menu()
    elif action == "trakt_watchlist":
        trakt_watchlist()
    elif action == "trakt_link":  
        link_trakt_account() 
    elif action == "tv_shows":
        tv_shows_menu()
    elif action == "movie_popular":
        list_movies("movie_popular", page)
    elif action == "movie_top_rated":
        list_movies("movie_top_rated", page)
    elif action == "movie_now_playing":
        list_movies("movie_now_playing", page)
    elif action == "movie_upcoming":
        list_movies("movie_upcoming", page)
    elif action == "movie_genres":
        movie_genres()
    elif action == "movie_genre":
        movies_by_genre(params.get("id"), page, params.get("name", ""))
    elif action == "tv_popular":
        list_tv_shows("tv_popular", page)
    elif action == "tv_top_rated":
        list_tv_shows("tv_top_rated", page)
    elif action == "tv_on_air":
        list_tv_shows("tv_on_air", page)
    elif action == "tv_genres":
        tv_genres()
    elif action == "tv_genre":
        tv_by_genre(params.get("id"), page, params.get("name", ""))
    elif action == "movie_trending":
        list_movies("movie_trending", int(params.get("page", 1)))
    elif action == "tv_trending":
        list_tv_shows("tv_trending", int(params.get("page", 1)))
    elif action == "tv_airing_today":
        list_tv_shows("tv_airing_today", int(params.get("page", 1)))
    elif action == "season_episodes":
        season_episodes(
            params.get("id"), 
            int(params.get("season", 1)),
            params.get("show_title", "")
        )
    elif action == "search":
        search_menu()
    elif action == "keyboard_search":
        keyboard_search()
    elif action == "play_movie":
        play_stream(
            params.get("ttid"), 
            params.get("title", "Movie"),
            from_watchlist=params.get("from_watchlist", "false")
        )
    elif action == "play_tv":
        play_tv_stream(
            params.get("tv_id"),
            int(params.get("season", 1)),
            int(params.get("episode", 1)),
            params.get("title", "TV Episode"),
            from_watchlist=params.get("from_watchlist", "false")
        )
    elif action == "play_movie_subs":
        play_stream_with_subs(
            params.get("ttid"),
            params.get("title", "Movie"),
            tmdb_id=params.get("tmdb_id"),
            media_type="movie",
            from_watchlist=params.get("from_watchlist", "false")
        )
    elif action == "play_tv_subs":
        play_tv_stream_with_subs(
            params.get("tv_id"),
            int(params.get("season", 1)),
            int(params.get("episode", 1)),
            params.get("title", "TV Episode"),
            tmdb_id=params.get("tmdb_id"),
            from_watchlist=params.get("from_watchlist", "false")
        )
    elif action == "movie_details":
        enhanced_media_details("movie", params.get("id"))
    elif action == "tv_details":
        enhanced_media_details("tv", params.get("id"))
    elif action == "season_episodes":
        enhanced_season_episodes(
            params.get("id"), 
            int(params.get("season", 1)),
            params.get("show_title", "")
        )
    elif action == "episode_details":  
        enhanced_episode_details(
            params.get("tv_id"),
            int(params.get("season", 1)),
            int(params.get("episode", 1)),
            params.get("show_title", "")
        )
    elif action == "trakt_add_watchlist":
        imdb_id = params.get("imdb_id")
        if imdb_id:
            success = trakt_add_to_watchlist_simple(imdb_id)
            if success:
                xbmc.executebuiltin("Container.Refresh()")
    elif action == "trakt_remove_watchlist":
        imdb_id = params.get("imdb_id")
        if imdb_id:
            success = trakt_remove_from_watchlist_simple(imdb_id)
            if success:
                xbmc.executebuiltin("Container.Refresh()")
    elif action == "trakt_add_tv_watchlist":
        tvdb_id = params.get("tvdb_id")
        if tvdb_id:
            success = trakt_add_tv_to_watchlist_simple(tvdb_id)
            if success:
                xbmc.executebuiltin("Container.Refresh()")
    elif action == "trakt_remove_tv_watchlist":
        tvdb_id = params.get("tvdb_id")
        if tvdb_id:
            success = trakt_remove_tv_from_watchlist_simple(tvdb_id)
            if success:
                xbmc.executebuiltin("Container.Refresh()")
    else:
        main_menu()

if __name__ == "__main__":
    router(sys.argv[2][1:])