# -*- coding: utf-8 -*-
import sys, os, time, json, urllib.parse
import xbmcgui, xbmcaddon, xbmcplugin, xbmcvfs
from urllib.parse import parse_qsl
import requests
from modules import export_import, zip_tools, utils
import modules.rdmagnet_importer as rdmagnet_importer
import xbmc
xbmc.sleep(150)  # Prevents widget race-condition during Kodi home refresh

ICON_PATH = xbmcaddon.Addon().getAddonInfo("path") + "/resources/icons/"
# INDEX_URL_SORTED = "https://uck.st/splite_movies/list_sorted/index.json"
ICON_MAP = {
    # SEARCH
    "Search Movies": "search.png",
    "Search Last View": "history.png",
    
    # TOP AND NEW  
    "Recently Added": "movies.png",
    "All Movies (Clean)": "movies.png",    
    "2025 (Clean)": "search_by_year.png",
    "2024 (Clean)": "search_by_year.png",
    
    # GENRE / YEAR / DECADE (FIXED)
    "Years (Clean)": "search_by_year.png",
    "Genres (Clean)": "search_by_genre.png",
    "Decades (Clean)": "search_by_decade.png",
    "A to Z (Clean)": "search_by_decade.png",
    
    "All Movies (Raw)": "movies.png",
    "Years Multi (Raw)": "search_by_year.png",
    "Genres Multi (Raw)": "search_by_genre.png", 
    "Decades Multi (Raw)": "search_by_decade.png",
    "A to Z Multi (Raw)": "search_by_decade.png",
    "Combo Multi (Raw)": "search_by_decade.png",
      
    # MOVIE LIST"
    "View Last Multi (Raw)": "folders.png",

    # PLAYBACK
    "Cloud": "cloud.png",
    "History": "history.png",
    "Local": "folders.png",

    # CLOUD MANAGER
    "Download": "download.png",
    "Send Magnet": "send_magnet.png",
    "Delete Magnet": "delete.png",
    "Unrestrict Link": "delete.png",

    # STATUS
    "RD Status": "rd_status.png",
    "API Status": "api_status.png",
    "API Key Injector": "tools.png",

    # FILE MANAGEMENT
    "Directory Tools": "folders.png",
}

ADDON_ID = "plugin.program.rdtplayer"
HANDLE   = int(sys.argv[1]) if len(sys.argv) > 1 else -1
PLUGIN_URL = sys.argv[0]

ADDON = xbmcaddon.Addon(id=ADDON_ID)   # <-- YOU WERE MISSING THIS

import sys, urllib.parse

def get_params():
    params = {}
    if len(sys.argv) > 1:
        args = sys.argv[1:]
        for arg in args:
            if arg.startswith("mode="):
                key, val = arg.split("=", 1)
                params[key] = val
    return params

params = get_params()
mode = params.get("mode")
if mode == "play":
    import xbmcgui, xbmc
    from modules import rdmagnet_importer
    magnet = params.get("magnet")
    if magnet:
        xbmcgui.Dialog().notification("Real-Debrid", "🎬 Playing cached media...", xbmcgui.NOTIFICATION_INFO, 2000)
        rdmagnet_importer.play_magnet(magnet)
    else:
        xbmcgui.Dialog().ok("Real-Debrid", "No magnet link found.")
    sys.exit()

# ------------------------ RD Token Helpers ------------------------
from modules.rd_auth_unified import get_rd_headers

BASE_URL = "https://api.real-debrid.com/rest/1.0"
HDRS = get_rd_headers()

def api_get(path, params=None, ok_codes=(200,)):
    try:
        r = requests.get(BASE_URL + path, headers=HDRS, params=params, timeout=15)
        if r.status_code not in ok_codes:
            xbmc.log(f"[RD] GET {path} -> {r.status_code}", xbmc.LOGWARNING)
            return None
        return r.json()
    except Exception as e:
        xbmc.log(f"[RD] GET error {path}: {e}", xbmc.LOGERROR)
        return None

def api_post(path, data=None, ok_codes=(200,)):
    try:
        r = requests.post(BASE_URL + path, headers=HDRS, data=data or {}, timeout=20)
        if r.status_code not in ok_codes:
            xbmc.log(f"[RD] POST {path} -> {r.status_code} / {r.text}", xbmc.LOGWARNING)
            return None
        return r.json() if r.text else {}
    except Exception as e:
        xbmc.log(f"[RD] POST error {path}: {e}", xbmc.LOGERROR)
        return None

def api_delete(path, ok_codes=(204, 200)):
    try:
        r = requests.delete(BASE_URL + path, headers=HDRS, timeout=15)
        if r.status_code not in ok_codes:
            xbmc.log(f"[RD] DELETE {path} -> {r.status_code}", xbmc.LOGWARNING)
            return False
        return True
    except Exception as e:
        xbmc.log(f"[RD] DELETE error {path}: {e}", xbmc.LOGERROR)
        return False

def build_url(qs_dict):
    return PLUGIN_URL + "?" + urllib.parse.urlencode(qs_dict)

def add_item(label, params, folder=True):
    li = xbmcgui.ListItem(label)

    import re
    clean_label = re.sub(r"\[/?COLOR[^\]]*\]", "", label)
    clean_label = clean_label.encode("ascii", "ignore").decode("ascii")
    clean_label = clean_label.lstrip(" .-*").strip()

    # ---------- ICON LOOKUP ----------
    icon_file = ICON_MAP.get(clean_label)
    if icon_file:
        li.setArt({
            "icon": ICON_PATH + icon_file,
            "thumb": ICON_PATH + icon_file,
            "fanart": ICON_PATH + "fanart.jpg"
        })
    else:
        li.setArt({"icon": "DefaultFolder.png"})

    # ---------- MEDIA INFO PANEL FIX ----------
    li.setInfo("video", {
        "title": clean_label,
        "plot": get_description_for(clean_label)
    })

    # ---------- URL ----------
    url = f"plugin://{ADDON_ID}/?{urllib.parse.urlencode(params)}"
    xbmcplugin.addDirectoryItem(HANDLE, url, li, folder)

def add_playable(label, play_url):
    li = xbmcgui.ListItem(label=label)
    li.setInfo("video", {"title": label})
    li.setProperty("IsPlayable", "true")
    xbmcplugin.addDirectoryItem(HANDLE, build_url({"action":"play_direct","url": play_url}), li, False)

# ------------------------ Core features ------------------------
def play_unrestricted(link):
    """
    Smart RD player — works for Cloud, History, or hoster links.
    Also logs responses for debugging.
    """
    import json

    xbmcgui.Dialog().notification("Real-Debrid", "Resolving stream...", xbmcgui.NOTIFICATION_INFO, 2000)

    # Try /unrestrict/link first
    resolved = None
    name = "Video"

    try:
        # Sometimes History items are IDs or dicts, not direct URLs
            # Handle JSON-encoded dicts from history
        if isinstance(link, str) and link.strip().startswith("{"):
            try:
                link = json.loads(link)
            except:
                pass
    
        if isinstance(link, dict):
            if link.get("link"):
                test_link = link["link"]
                name = link.get("filename", "Video")
            elif link.get("download"):
                test_link = link["download"]
            elif link.get("links"):
                test_link = link["links"][0]
            else:
                xbmcgui.Dialog().notification("Real-Debrid", "Invalid RD item", xbmcgui.NOTIFICATION_ERROR)
                return
        else:
            test_link = link
    
        data = api_post("/unrestrict/link", {"link": test_link})
        xbmc.log(f"[RD Tools Debug] Unrestrict result: {json.dumps(data, indent=2)}", xbmc.LOGINFO)

        if data and "download" in data:
            resolved = data["download"]
            name = data.get("filename", os.path.basename(resolved))
    except Exception as e:
        xbmc.log(f"[RD Tools Error] Exception: {e}", xbmc.LOGERROR)

    if not resolved:
        xbmcgui.Dialog().notification("Real-Debrid", "Could not resolve link", xbmcgui.NOTIFICATION_ERROR)
        return

    # Close overlays
    xbmc.executebuiltin('Dialog.Close(all,true)')
    xbmc.sleep(200)

    # Play
    li = xbmcgui.ListItem(path=resolved)
    li.setInfo("video", {"title": name})
    li.setProperty("IsPlayable", "true")

    if HANDLE != -1:
        xbmcplugin.setResolvedUrl(HANDLE, True, li)
    else:
        xbmc.Player().play(resolved)

    xbmc.log(f"[RD Tools] Playing: {name}", xbmc.LOGINFO)

def list_cloud():
    xbmcplugin.setPluginCategory(HANDLE, "Real-Debrid  Cloud")
    xbmcplugin.setContent(HANDLE, "files")

    torrents = api_get("/torrents") or []
    for tor in torrents:
        tid   = tor.get("id")
        name  = tor.get("filename", "Unknown")
        li    = xbmcgui.ListItem(label=name)

        # context menu: Play / Download / Delete
        cm = [
            ("Play",     f'RunPlugin({build_url({"action":"cloud_files","id":tid,"mode":"play"})})'),
            ("Download", f'RunPlugin({build_url({"action":"cloud_files","id":tid,"mode":"download"})})'),
            ("Delete",   f'RunPlugin({build_url({"action":"delete_torrent","id":tid})})'),
        ]
        li.addContextMenuItems(cm, replaceItems=False)

        xbmcplugin.addDirectoryItem(HANDLE, build_url({"action":"cloud_files","id":tid}), li, True)

    xbmcplugin.endOfDirectory(HANDLE)

def cloud_files(tid, mode=None):
    info = api_get(f"/torrents/info/{tid}") or {}
    links = info.get("links", [])
    files = info.get("files", [])

    # Build display list
    names = []
    for i, fobj in enumerate(files):
        try:
            names.append(fobj.get("path", f"File {i+1}"))
        except Exception:
            names.append(f"File {i+1}")

    # If launched as a folder view, list files
    if not mode:
        for i, name in enumerate(names):
            li = xbmcgui.ListItem(label=name)
            li.setProperty("IsPlayable", "true")
            url = build_url({"action":"play_link","link": links[i] if i < len(links) else ""})
            cm  = [
                ("Play",     f'RunPlugin({url})'),
                ("Download", f'RunPlugin({build_url({"action":"download_file","link": links[i] if i < len(links) else ""})})')
            ]
            li.addContextMenuItems(cm, replaceItems=False)
            xbmcplugin.addDirectoryItem(HANDLE, url, li, False)
        xbmcplugin.endOfDirectory(HANDLE)
        return

    # Quick actions triggered from context in the torrent row
    if mode == "play":
        idx = xbmcgui.Dialog().select("Select file to play", names)
        if idx >= 0 and idx < len(links):
            play_unrestricted(links[idx])
        return
    if mode == "download":
        idx = xbmcgui.Dialog().select("Select file to download", names)
        if idx >= 0 and idx < len(links):
            download_file_prompt(links[idx], names[idx] if idx < len(names) else "video")
        return

def list_history():
    xbmcplugin.setPluginCategory(HANDLE, "Real-Debrid  History")
    xbmcplugin.setContent(HANDLE, "files")
    items = api_get("/downloads") or []

    for it in items:
        label = it.get("filename", "Unknown")

        # Prefer 'download', but fall back to first 'links' entry
        link = it.get("download") or (it.get("links")[0] if it.get("links") else None)
        if not link:
            continue

        # Wrap link + filename in a dict so play_unrestricted can detect source type
        wrapped = json.dumps({"link": link, "filename": label})
        li = xbmcgui.ListItem(label=label)
        li.setInfo("video", {"title": label})
        li.setProperty("IsPlayable", "true")
        xbmcplugin.addDirectoryItem(
            HANDLE,
            build_url({"action": "play_link", "link": wrapped}),
            li,
            False
        )

    xbmcplugin.endOfDirectory(HANDLE)

def delete_torrent_flow():
    torrents = api_get("/torrents") or []
    if not torrents:
        xbmcgui.Dialog().notification("Real-Debrid", "No torrents", xbmcgui.NOTIFICATION_INFO)
        return

    # Build a display list of filenames
    names = [t.get("filename", "Unknown") for t in torrents]

    # Multi-select dialog
    selected = xbmcgui.Dialog().multiselect(
        "Select torrents to delete", names, useDetails=False
    )

    if not selected:
        return

    # Confirm deletion
    if not xbmcgui.Dialog().yesno(
        "Confirm Delete",
        f"Delete {len(selected)} selected torrent(s)?"
    ):
        return

    deleted = 0
    failed = 0

    for idx in selected:
        tid = torrents[idx].get("id")
        if not tid:
            continue
        ok = api_delete(f"/torrents/delete/{tid}")
        if ok:
            deleted += 1
        else:
            failed += 1

    msg = f" Deleted {deleted}"
    if failed:
        msg += f" |  Failed {failed}"

    xbmcgui.Dialog().notification("Real-Debrid", msg, xbmcgui.NOTIFICATION_INFO)

def rd_full_diagnostics():
    """
    Ultra-clean RD diagnostics (API Key only).
    No ResolveURL token logic.
    No technical clutter.
    Shows ONLY what end users understand.
    """

    api_key = ADDON.getSetting("api_key")
    authorized = bool(api_key)

    # If no API key  no need to test anything else
    if not authorized:
        report = (
            "REAL-DEBRID STATUS\n"
            "------------------------------\n"
            "Authorization Method: None\n"
            "Authorized: No\n\n"
            "RESULT\n"
            "------------------------------\n"
            " No API key found.\n"
            "Enter your Real-Debrid API key in Settings."
        )
        xbmcgui.Dialog().textviewer("RD Status", report)
        return

    # Try to validate the API key using /user endpoint
    user = api_get("/user")
    if not user:
        valid = False
    else:
        valid = True

    # Determine final result message
    if valid:
        result_msg = (
            " Your API key is valid.\n"
            " Real-Debrid is fully authorized.\n"
            " Playback and cloud features are ready."
        )
    else:
        result_msg = (
            " Your API key appears invalid.\n"
            "Try re-entering it in Settings."
        )

    # Build report
    report = (
        "REAL-DEBRID STATUS\n"
        "------------------------------\n"
        "Authorization Method: API Key\n"
        f"API Key Present: {'Yes' if authorized else 'No'}\n"
        f"API Key Valid:   {'Yes' if valid else 'No'}\n\n"
        "RESULT\n"
        "------------------------------\n"
        f"{result_msg}\n"
    )

    xbmcgui.Dialog().textviewer("RD Status", report)

# =============================================================================
# LIST SUPPORTED HOSTS
# =============================================================================

def list_supported_hosts():
    """
    Scrollable, formatted viewer for Real-Debrid supported hosts.
    Also saves a copy locally for offline access.
    """
    xbmcgui.Dialog().notification("Real-Debrid", "Fetching supported hosts...", xbmcgui.NOTIFICATION_INFO, 1500)
    try:
        response = api_get("/hosts") or {}
        if not response:
            xbmcgui.Dialog().notification("Real-Debrid", "Failed to fetch supported hosts", xbmcgui.NOTIFICATION_ERROR)
            return

        # Format the list
        hosts = []
        for host, domains in response.items():
            domain_str = ", ".join(domains)
            hosts.append(f"[B]{host}[/B]\n  [COLOR gray]{domain_str}[/COLOR]")

        hosts.sort()
        formatted_text = "\n\n".join(hosts)
        total_hosts = len(hosts)

        #  Show in scrollable text viewer
        xbmcgui.Dialog().textviewer(f"Real-Debrid Supported Hosts ({total_hosts})", formatted_text)

        #  Save a local cached copy
        try:
            import xbmcvfs
            cache_dir = xbmcvfs.translatePath("special://profile/addon_data/plugin.program.rdtplayer")
            if not xbmcvfs.exists(cache_dir):
                xbmcvfs.mkdirs(cache_dir)

            cache_file = os.path.join(cache_dir, "hosts.txt")
            with xbmcvfs.File(cache_file, 'w') as f:
                f.write(formatted_text)
            xbmcgui.Dialog().notification("Real-Debrid", f"Saved to hosts.txt ({total_hosts} hosts)", xbmcgui.NOTIFICATION_INFO, 3000)
        except Exception as fe:
            xbmc.log(f"[RDTools] Failed to write hosts cache: {fe}", xbmc.LOGERROR)

    except Exception as e:
        xbmcgui.Dialog().ok("Real-Debrid", f"Error fetching hosts:\n{e}")

def download_file_prompt(link, default_name="video"):
    # unrestrict to get direct file URL (and filename if provided)
    data = api_post("/unrestrict/link", {"link": link})
    if not data or "download" not in data:
        xbmcgui.Dialog().notification("Real-Debrid", "Unrestrict failed", xbmcgui.NOTIFICATION_ERROR)
        return
    url  = data["download"]
    name = data.get("filename", default_name)

    dest_dir = xbmcgui.Dialog().browse(3, "Choose download folder", "files")  # type 3 = directories
    if not dest_dir:
        return
    dest_path = os.path.join(dest_dir, name)

    try:
        with requests.get(url, headers=HDRS, stream=True, timeout=60) as r:
            r.raise_for_status()
            # ensure path exists
            try:
                if not xbmcvfs.exists(dest_dir):
                    xbmcvfs.mkdirs(dest_dir)
            except Exception:
                pass
            # write file
            with open(dest_path, "wb") as f:
                for chunk in r.iter_content(chunk_size=1024 * 256):
                    if not chunk: break
                    f.write(chunk)
        xbmcgui.Dialog().notification("Download", f"Saved:\n{os.path.basename(dest_path)}", xbmcgui.NOTIFICATION_INFO, 4000)
    except Exception as e:
        xbmc.log(f"[RD] Download error: {e}", xbmc.LOGERROR)
        xbmcgui.Dialog().notification("Download", "Failed", xbmcgui.NOTIFICATION_ERROR)

def play_local_downloads():
    """
    Dual-mode local video player:
    📁 Normal View  – browse all files/folders
    🎞 Video-Only View – show only playable videos
    ✅ Auto-detects SD card paths and copies to temp before playback
    """
    import os, xbmc, xbmcgui, xbmcvfs, shutil

    playable_exts = (".mp4", ".mkv", ".avi", ".mov", ".wmv", ".flv", ".ts", ".m4v", ".webm")
    mask = ".mkv|.mp4|.avi|.mov|.wmv|.flv|.ts|.m4v|.webm"

    def play_file(path):
        """Play file safely (auto-copy if on SD or restricted path)."""
        resolved = xbmcvfs.translatePath(path)
        xbmc.log(f"[RD TOOLS] Preparing to play: {resolved}", xbmc.LOGINFO)

        # Detect SD/removable storage paths
        if "/storage/" in resolved and not resolved.startswith("/storage/emulated/0"):
            try:
                xbmcgui.Dialog().notification("Real-Debrid", "Copying file to temp for playback...", xbmcgui.NOTIFICATION_INFO, 3000)
                temp_path = os.path.join(xbmcvfs.translatePath("special://temp/"), os.path.basename(resolved))
                xbmc.log(f"[RD TOOLS] Copying from SD card to temp: {temp_path}", xbmc.LOGINFO)
                xbmcvfs.copy(resolved, temp_path)
                resolved = temp_path
            except Exception as e:
                xbmc.log(f"[RD TOOLS] SD copy failed: {e}", xbmc.LOGERROR)
                xbmcgui.Dialog().ok("Real-Debrid", f"Could not copy file for playback:\n{e}")
                return

        li = xbmcgui.ListItem(label=os.path.basename(resolved))
        li.setInfo("video", {"title": os.path.basename(resolved)})
        li.setProperty("IsPlayable", "true")
        xbmc.Player().play(resolved, li)
        xbmcgui.Dialog().notification("Real-Debrid", "Playing file...", xbmcgui.NOTIFICATION_INFO, 3000)

    # ───────────────────────────────
    # 0️⃣ Choose browsing mode
    # ───────────────────────────────
    mode = xbmcgui.Dialog().select(
        "Choose how to browse",
        ["📁 Normal View (show all files)", "🎞 Video-Only View"]
    )
    if mode == -1:
        return

        # ───────────────────────────────
    # 1️⃣ Normal View  (full navigation enabled)
    # ───────────────────────────────
    if mode == 0:
        file_path = xbmcgui.Dialog().browse(
            1,                               # 1 = ShowAndGetFile
            "Select Video File to Play",
            "files",                         # ✅ "files" instead of "video" so user can browse anywhere
            ".mkv|.mp4|.avi|.mov|.wmv|.flv|.ts|.m4v|.webm",
            False,
            False,
            "",                              # ✅ blank default_path → unrestricted navigation
        )

        if not file_path:
            return

        resolved = xbmcvfs.translatePath(file_path)
        xbmc.log(f"[RD TOOLS] Normal View selected: {resolved}", xbmc.LOGINFO)

        # Handle if folder chosen or file lacks playable extension
        if xbmcvfs.exists(file_path):
            dirs, files = xbmcvfs.listdir(file_path)
            if files:
                playable = [f for f in files if f.lower().endswith(playable_exts)]
                if not playable:
                    xbmcgui.Dialog().ok("Real-Debrid", "No playable files found here.")
                    return
                sel = xbmcgui.Dialog().select("Select a File to Play", playable)
                if sel == -1:
                    return
                resolved = os.path.join(resolved, playable[sel])
                file_path = resolved

        play_file(file_path)
        return

    # ───────────────────────────────
    # 2️⃣ Video-Only View
    # ───────────────────────────────
    folder = xbmcgui.Dialog().browse(
        0,
        "Select Folder Containing Videos",
        "files",
        "",
        False,
        False,
        "special://home/"
    )
    if not folder:
        return

    resolved = xbmcvfs.translatePath(folder)
    dirs, files = xbmcvfs.listdir(folder)
    all_files = list(files)
    if not all_files:
        try:
            all_files = os.listdir(resolved)
        except Exception:
            all_files = []
    playable = [f for f in all_files if f.lower().endswith(playable_exts)]
    if not playable:
        xbmcgui.Dialog().ok("Real-Debrid", "No playable video files found here.")
        return

    sel = xbmcgui.Dialog().select("Select Video File", playable)
    if sel == -1:
        return

    file_path = os.path.join(resolved, playable[sel])
    play_file(file_path)


def account_info():
    info = api_get("/user") or {}
    if not info:
        xbmcgui.Dialog().notification("Real-Debrid", "Could not read account", xbmcgui.NOTIFICATION_ERROR)
        return
    # prettify
    premium = "Yes" if info.get("type") == "premium" else "No"
    exp = info.get("premium_until") or info.get("expiration") or ""
    points = str(info.get("points", ""))
    lines = [
        "",
        f"  Username:  {info.get('username','')}",
        f"  Email:     {info.get('email','')}",
        f"  Premium:   {premium}",
        f"  Expires:   {exp}",
        f"  Points:     {points}",
        "",
    ]
    xbmcgui.Dialog().textviewer("Real-Debrid Account", "\n".join(lines))    

def get_description_for(name):
    descriptions = {       
        "Search Movies": "Search all movies by title or plot.",
        "Search Last View": "View the last search results.",
        "Recently Added": "View all Movies Recently Added.",
        "All Movies (Clean)": "View all movies in list newest first.", 
        "2025 (Clean)": "Browse movies sorted by release year.",
        "2024 (Clean)": "Browse movies sorted by release year.",
        "Years (Clean)": "Browse movies sorted by release year.",
        "Genres (Clean)": "Browse movies sorted by genre.",
        "Decades (Clean)": "Browse movies grouped by decade.",         
        "A to Z (Clean)": "Browse movies sorted by A to Z.",  
     
        "All Movies (Raw)": "View all movies in list newest first.", 
        "Years (Raw)": "Browse movies sorted by release year.",
        "Genres (Raw)": "Browse movies sorted by genre.",
        "Decades (Raw)": "Browse movies grouped by decade.",         
        "A to Z (Raw)": "Browse movies sorted by A to Z.",  
        "Combo Multi (Raw)": "Filter movies", 

        "View Last Multi (Raw)": "Open the multi-view browser.",     
       
        "Cloud": "View files stored in your Real-Debrid cloud.",
        "History": "View your Real-Debrid download history.",
        "Local": "Play local files from your device.",
        "Download": "Download files from your Real-Debrid cloud.",
        "Send Magnet": "Send a magnet link to Real-Debrid.",
        "Delete Magnet": "Delete magnets from Real-Debrid cloud.",
        "Unrestrict Link": "Unrestrict Link URL Link.",      
        "RD Status": "View your Real-Debrid account status.",
        "API Status": "Check Real-Debrid API status.",
        "API Key Injector": "Inject or update your Real-Debrid API key.",
        "Directory Tools": "Import or export addon folders and data."
    }
    return descriptions.get(name, name)

def show_root():
    xbmcplugin.setPluginCategory(HANDLE, "Real-Debrid Tools")
    xbmcplugin.setContent(HANDLE, "files")

    # ---------------- SEARCH ----------------
    add_item("[COLOR gold]Search by Title or Plot[/COLOR]", {"action": "noop"}, False)
    add_item("Search Movies", {"action": "search_text"})
    add_item("Search Last View", {"action": "mag_browser_v4_w4"})
    
    # ---------------- RECENTLY ADDED ----------------    
    add_item("[COLOR gold]Movies Recently Added[/COLOR]", {"action": "noop"}, False)     
    add_item("Recently Added", {"action": "mag_browser_v4_top_movies"})
    add_item("[COLOR gray]not all search indexed[/COLOR]", {"action": "noop"}, False)   
      
    # ---------------- MOVIE LIST ----------------
    add_item("[COLOR gold]Movies List[/COLOR]", {"action": "noop"}, False) 
    add_item("[COLOR gold]De-duplicated - Yes[/COLOR]", {"action": "noop"}, False)         
    add_item("All Movies (Clean)", {"action": "all_movies_clean"})  
    add_item("2025 (Clean)", {"action": "202x_movies_clean"}) 
    add_item("2024 (Clean)", {"action": "2024_movies_clean"}) 
    add_item("Years (Clean)", {"action": "sorted", "mode": "years"})
    add_item("Genres (Clean)", {"action": "sorted", "mode": "genres"})
    add_item("Decades (Clean)", {"action": "sorted", "mode": "decades"})
    add_item("A to Z (Clean)", {"action": "sorted", "mode": "letters"})    
    
   # ---------------- MULTI VIEW ----------------
    add_item("[COLOR gold]Movie List Multi View[/COLOR]", {"action": "noop"}, False) 
    add_item("[COLOR gold]De-duplicated - No[/COLOR]", {"action": "noop"}, False)            
    add_item("All Movies (Raw)", {"action": "mag_browser_v4_all"})
    add_item("Years Multi (Raw)", {"action": "custom_search_year"})
    add_item("Genres Multi (Raw)", {"action": "custom_search"})    
    add_item("Decades Multi (Raw)", {"action": "custom_search_decade"})  
    add_item("A to Z Multi (Raw)", {"action": "custom_search_letters"})
    add_item("Combo Multi (Raw)", {"action": "custom_search_combo"})
    
    # ---------------- Last Multi View ----------------   
    add_item("[COLOR gold]Last Multi View[/COLOR]", {"action": "noop"}, False)
    add_item("View Last Multi (Raw)", {"action": "multi_list"})
    
    # ---------------- PLAYBACK ----------------
    add_item("[COLOR gold]Play From[/COLOR]", {"action": "noop"}, False)
    add_item("Cloud", {"action": "cloud"})
    add_item("History", {"action": "history"})
    add_item("Local", {"action": "play_local"})

    # ---------------- CLOUD MANAGER ----------------
    add_item("[COLOR gold]Cloud Manager[/COLOR]", {"action": "noop"}, False)
    add_item("Download", {"action": "download_flow"})
    add_item("Send Magnet", {"action": "add_magnet"})
    add_item("Delete Magnet", {"action": "delete_flow"})
    add_item("Unrestrict Link", {"action": "unrestrict_link"})

    # ---------------- RD STATUS ----------------
    add_item("[COLOR gold]Real-Debrid Status[/COLOR]", {"action": "noop"}, False)
    add_item("RD Status", {"action": "account"})
    add_item("API Status", {"action": "rd_diag_full"})
    add_item("API Key Injector ", {"action": "rd_injector"})

    # ---------------- FILE MANAGEMENT ----------------
    add_item("[COLOR gold]Manage Files & Folders[/COLOR]", {"action": "noop"}, False)
    add_item("Directory Tools", {"action": "export_import"})

    # ---------------- FOOTER ----------------
    li = xbmcgui.ListItem(label="[COLOR gold]Clean Menu Available in Settings[/COLOR]")
    li.setProperty("IsPlayable", "false")
    xbmcplugin.addDirectoryItem(HANDLE, "", li, False)

    xbmcplugin.endOfDirectory(HANDLE)

# ------------------------ Router ------------------------

def show_sorted_group(group_key):
    try:
        r = requests.get(INDEX_URL_SORTED, timeout=6)
        data = r.json() if r.ok else {}
    except Exception as e:
        xbmcgui.Dialog().ok("RD Tools", f"Failed to load index:\n{e}")
        return

    entries = data.get(group_key, [])
    if not entries:
        xbmcgui.Dialog().ok("RD Tools", f"No entries for {group_key}")
        return

    # ===========================
    # SORT FIXES (FINAL VERSION)
    # ===========================
    try:
        if group_key == "years":
            # Newest year -> first (DESCENDING)
            entries = sorted(entries, key=lambda x: int(x.get("label", 0)), reverse=True)

        elif group_key == "decades":
            # Newest decade -> first (DESCENDING)
            entries = sorted(entries, key=lambda x: int(x.get("label", 0)), reverse=True)

        elif group_key == "genres":
            # Alphabetical A  Z
            entries = sorted(entries, key=lambda x: x.get("label", "").lower())

        elif group_key == "letters":
        # Alphabetical A�Z, # last
            entries = sorted(
                entries,
                key=lambda x: ("ZZZ" if x.get("label") == "#" else x.get("label", "").upper())
            )

    except Exception:
        pass
    # ===========================

    xbmcplugin.setContent(HANDLE, "files")

    for entry in entries:
        label = entry.get("label", "Unknown")
        file_url = entry.get("file", "")
        url = (
            f"plugin://{ADDON_ID}/?action=sorted_list"
            f"&group={group_key}"
            f"&label={urllib.parse.quote(label)}"
            f"&file_url={urllib.parse.quote(file_url)}"
        )
        li = xbmcgui.ListItem(label)
        xbmcplugin.addDirectoryItem(HANDLE, url, li, True)

    xbmcplugin.endOfDirectory(HANDLE)

import re

def normalize_title(title):
    if not title:
        return ""
    return re.sub(r'[^a-z0-9]', '', title.lower())
    
import re

def extract_movie_title(raw):
    if not raw:
        return ""

    # Replace separators with spaces
    t = re.sub(r'[._]', ' ', raw)

    # Remove year and everything after it
    t = re.split(r'\b(19|20)\d{2}\b', t)[0]

    # Remove common junk words
    t = re.sub(
        r'\b(bluray|bdrip|bdremux|webrip|webdl|hdr|uhd|x264|x265|hevc|aac|dts|truehd|atmos|remux|multi)\b',
        '',
        t,
        flags=re.I
    )

    # Cleanup
    t = re.sub(r'\s+', ' ', t).strip().lower()

    return t
    
def show_sorted_list(group_key, label, file_url):
    try:
        r = requests.get(file_url, timeout=10)
        movies = r.json() if r.ok else []
    except Exception as e:
        xbmcgui.Dialog().ok("RD Tools", f"Failed to load list:\n{e}")
        return

    if not movies:
        xbmcgui.Dialog().ok("RD Tools", f"Empty list:\n{label}")
        xbmcplugin.endOfDirectory(HANDLE)
        return

    # -------------------------------
    # COLLAPSE MOVIES BY TITLE+YEAR
    # -------------------------------
    grouped = {}

    for m in movies:
        raw_title = m.get("title", "") or ""
        year = str(m.get("year", "")).strip()

        try:
            base_title = extract_movie_title(raw_title)
        except Exception:
            base_title = raw_title.lower() if raw_title else "unknown"

        key = base_title + (year if year else "")
        grouped.setdefault(key, []).append(m)

    xbmcplugin.setContent(HANDLE, "movies")

    for variants in grouped.values():
        first = variants[0]

        title = first.get("title", "Unknown")
        year  = first.get("year", "")
        label_txt = f"{title} ({year})" if year else title

        url = (
            f"plugin://{ADDON_ID}/"
            f"?action=movie_variants"
            f"&data={urllib.parse.quote(json.dumps(variants))}"
        )

        li = xbmcgui.ListItem(label_txt)

        li.setInfo("video", {
            "title": title,
            "year": year,
            "plot": first.get("plot", ""),
            "rating": first.get("rating", 0),
            "mediatype": "movie",
        })

        li.setArt({
            "poster": first.get("poster", ""),
            "fanart": first.get("fanart", ""),
            "clearlogo": first.get("clearlogo", ""),
        })

        #  THIS IS THE LINE YOU WERE MISSING / MIS-INDENTED
        xbmcplugin.addDirectoryItem(HANDLE, url, li, True)

    #  ALSO REQUIRED
    xbmcplugin.endOfDirectory(HANDLE)

def show_all_movies_clean():
    from modules.rdmagnet_browser_v4_all import get_master_movie_list

    movies = get_master_movie_list()
    if not movies:
        xbmcgui.Dialog().ok("RD Tools", "No movies found.")
        return

    grouped = {}

    for m in movies:
        raw_title = m.get("title", "")
        year = str(m.get("year", "")).strip()
    
        try:
            base_title = extract_movie_title(raw_title)
        except Exception:
            base_title = raw_title.lower() if raw_title else "unknown"
    
        key = base_title
        if year:
            key += year
    
        grouped.setdefault(key, []).append(m)

    xbmcplugin.setContent(HANDLE, "movies")

    for variants in grouped.values():
        first = variants[0]

        title = first.get("title", "Unknown")
        year  = first.get("year", "")
        label = f"{title} ({year})" if year else title

        url = (
            f"plugin://{ADDON_ID}/"
            f"?action=movie_variants"
            f"&data={urllib.parse.quote(json.dumps(variants))}"
        )

        li = xbmcgui.ListItem(label)
        li.setInfo("video", {
            "title": title,
            "year": year,
            "plot": first.get("plot", ""),
            "rating": first.get("rating", ""),
            "mediatype": "movie"
        })
        li.setArt({
            "poster": first.get("poster"),
            "fanart": first.get("fanart"),
            "clearlogo": first.get("clearlogo", "")
        })

        xbmcplugin.addDirectoryItem(HANDLE, url, li, True)

    xbmcplugin.endOfDirectory(HANDLE)

def show_202x_movies_clean():
    from modules.rdmagnet_browser_v4_202x import get_master_movie_list

    movies = get_master_movie_list()
    if not movies:
        xbmcgui.Dialog().ok("RD Tools", "No movies found.")
        return

    grouped = {}

    for m in movies:
        raw_title = m.get("title", "")
        year = str(m.get("year", "")).strip()
    
        try:
            base_title = extract_movie_title(raw_title)
        except Exception:
            base_title = raw_title.lower() if raw_title else "unknown"
    
        key = base_title
        if year:
            key += year
    
        grouped.setdefault(key, []).append(m)

    xbmcplugin.setContent(HANDLE, "movies")

    for variants in grouped.values():
        first = variants[0]

        title = first.get("title", "Unknown")
        year  = first.get("year", "")
        label = f"{title} ({year})" if year else title

        url = (
            f"plugin://{ADDON_ID}/"
            f"?action=movie_variants"
            f"&data={urllib.parse.quote(json.dumps(variants))}"
        )

        li = xbmcgui.ListItem(label)
        li.setInfo("video", {
            "title": title,
            "year": year,
            "plot": first.get("plot", ""),
            "rating": first.get("rating", ""),
            "mediatype": "movie"
        })
        li.setArt({
            "poster": first.get("poster"),
            "fanart": first.get("fanart"),
            "clearlogo": first.get("clearlogo", "")
        })

        xbmcplugin.addDirectoryItem(HANDLE, url, li, True)

    xbmcplugin.endOfDirectory(HANDLE)

def show_2024_movies_clean():
    from modules.rdmagnet_browser_v4_2024 import get_master_movie_list

    movies = get_master_movie_list()
    if not movies:
        xbmcgui.Dialog().ok("RD Tools", "No movies found.")
        return

    grouped = {}

    for m in movies:
        raw_title = m.get("title", "")
        year = str(m.get("year", "")).strip()
    
        try:
            base_title = extract_movie_title(raw_title)
        except Exception:
            base_title = raw_title.lower() if raw_title else "unknown"
    
        key = base_title
        if year:
            key += year
    
        grouped.setdefault(key, []).append(m)

    xbmcplugin.setContent(HANDLE, "movies")

    for variants in grouped.values():
        first = variants[0]

        title = first.get("title", "Unknown")
        year  = first.get("year", "")
        label = f"{title} ({year})" if year else title

        url = (
            f"plugin://{ADDON_ID}/"
            f"?action=movie_variants"
            f"&data={urllib.parse.quote(json.dumps(variants))}"
        )

        li = xbmcgui.ListItem(label)
        li.setInfo("video", {
            "title": title,
            "year": year,
            "plot": first.get("plot", ""),
            "rating": first.get("rating", ""),
            "mediatype": "movie"
        })
        li.setArt({
            "poster": first.get("poster"),
            "fanart": first.get("fanart"),
            "clearlogo": first.get("clearlogo", "")
        })

        xbmcplugin.addDirectoryItem(HANDLE, url, li, True)

    xbmcplugin.endOfDirectory(HANDLE)


#        xbmcplugin.addDirectoryItem(HANDLE, url, li, True)

#    xbmcplugin.endOfDirectory(HANDLE)

def router(paramstring):
    params = dict(urllib.parse.parse_qsl(paramstring.lstrip("?")))
    action = params.get("action")

    if action is None:
        use_clean = ADDON.getSettingBool("use_clean_menu")
        xbmc.log(f"[RD TOOLS] use_clean_menu = {use_clean}", xbmc.LOGINFO)

        if use_clean:
            show_clean_menu()
        else:
            show_root()
        return
        
        # --- SORTED VIEWS (NEW) ---
    if action == "sorted":
        from modules.sorted_renderer import render
        render(HANDLE, ADDON_ID, params.get("mode"))
        return

    if action == "custom_search":
        from modules import custom_search
        custom_search.run_custom_search()
        return
        
    if action == "custom_search_year":
        from modules import custom_search_year
        custom_search_year.run_custom_search_year()
        return    

    if action == "custom_search_decade":
        from modules import custom_search_decade
        custom_search_decade.run_custom_search_decade()
        return      
        
    if action == "custom_search_letters":
        from modules import custom_search_letters
        custom_search_letters.run_custom_search_letters()
        return               
        
    if action == "custom_search_combo":
        from modules import custom_search_combo
        custom_search_combo.run_custom_search_combo()
        return

    if action == "search_text":
        from modules import search_text
        search_text.run_text_search()
        return
        
    if action == "multi_list":
        show_multi_list()
        return
   
    if action == "diamond_tools":
        show_diamond_dev_tools()
        return
        
    if action == "sorted_list":
        show_sorted_list(
            params.get("group", "genres"),
            urllib.parse.unquote(params.get("label", "")),
            urllib.parse.unquote(params.get("file_url", ""))
        )
        return
        
    if action == "movie_variants":
        variants = json.loads(urllib.parse.unquote(params.get("data", "[]")))
        from modules.rdmagnet_browser_v4_player import render_movie_list
        render_movie_list(variants, "Available Versions")
        return
           
    if action == "mag_browser_v4_top_movies":
        from modules import rdmagnet_browser_v4_top_movies
        try:
            rdmagnet_browser_v4_top_movies.build_movie_directory()
        except Exception as e:
            xbmc.log(f"[RD-Widget] v4_top_movies failed: {e}", xbmc.LOGWARNING)
            xbmcplugin.endOfDirectory(HANDLE)
        return
        
    if action == "mag_browser_v4_all":
        from modules import rdmagnet_browser_v4_all
        try:
            rdmagnet_browser_v4_all.build_movie_directory()
        except Exception as e:
            xbmc.log(f"[RD-Widget] v4_all failed: {e}", xbmc.LOGWARNING)
            xbmcplugin.endOfDirectory(HANDLE)
        return
                       
    if action == "all_movies_clean":
        show_all_movies_clean()
        return
        
    if action == "202x_movies_clean":
        show_202x_movies_clean()
        return               

    if action == "2024_movies_clean":
        show_2024_movies_clean()
        return               

    if action == "mag_browser_v4_w1":
        from modules import rdmagnet_browser_v4_w1
        try:
            rdmagnet_browser_v4_w1.build_movie_directory()
        except Exception as e:
            xbmc.log(f"[RD-Widget] v4_w1 failed: {e}", xbmc.LOGWARNING)
            xbmcplugin.endOfDirectory(HANDLE)
        return

    if action == "mag_browser_v4_w2":
        from modules import rdmagnet_browser_v4_w2
        try:
            rdmagnet_browser_v4_w2.build_movie_directory()
        except Exception as e:
            xbmc.log(f"[RD-Widget] v4_w2 failed: {e}", xbmc.LOGWARNING)
            xbmcplugin.endOfDirectory(HANDLE)
        return

    if action == "mag_browser_v4_w3":
        from modules import rdmagnet_browser_v4_w3
        try:
            rdmagnet_browser_v4_w3.build_movie_directory()
        except Exception as e:
            xbmc.log(f"[RD-Widget] v4_w3 failed: {e}", xbmc.LOGWARNING)
            xbmcplugin.endOfDirectory(HANDLE)
        return

    if action == "mag_browser_v4_w4":
        from modules import rdmagnet_browser_v4_w4
        try:
            rdmagnet_browser_v4_w4.build_movie_directory()
        except Exception as e:
            xbmc.log(f"[RD-Widget] v4_w4 failed: {e}", xbmc.LOGWARNING)
            xbmcplugin.endOfDirectory(HANDLE)
        return

    if action == "mag_browser_v4_w5":
        from modules import rdmagnet_browser_v4_w5
        try:
            rdmagnet_browser_v4_w5.build_movie_directory()
        except Exception as e:
            xbmc.log(f"[RD-Widget] v4_w5 failed: {e}", xbmc.LOGWARNING)
            xbmcplugin.endOfDirectory(HANDLE)
        return
        
    if action == "mag_browser_v4_w6":
        from modules import rdmagnet_browser_v4_w6
        try:
            rdmagnet_browser_v4_w6.build_movie_directory()
        except Exception as e:
            xbmc.log(f"[RD-Widget] v4_w6 failed: {e}", xbmc.LOGWARNING)
            xbmcplugin.endOfDirectory(HANDLE)
        return
           
        
    elif action == "add_to_cloud":
        from modules.rd_cloud_handler import add_to_cloud
        add_to_cloud(params.get("title", ""), params.get("magnet", ""))

    if action == "open_magnet_browser":
        import modules.rd_manager_browser as browser
        browser.show_browser()
        return

    if action == "cloud":
        list_cloud()
        return

    if action == "cloud_files":
        cloud_files(params.get("id"), params.get("mode"))
        return

    if action == "history":
        list_history()
        return

    if action == "play_link":
        link = params.get("link")
        if link:
            play_unrestricted(link)
        return

    if action == "add_magnet":
        try:
            import modules.rdmagnet_importer as rdmagnet_importer
            rdmagnet_importer.run()
        except Exception as e:
            xbmcgui.Dialog().ok("Error", f"Failed to launch RD Magnet Importer:\n{e}")
        return

    if action == "delete_torrent":
        tid = params.get("id")
        if tid:
            api_delete(f"/torrents/delete/{tid}")
        return
        
    if action == "unrestrict_link":
        try:
            import modules.rd_unrestrict_importer as rd_unrestrict_importer
            rd_unrestrict_importer.run()
        except Exception as e:
            xbmcgui.Dialog().ok("Error", f"Failed to launch RD Magnet Importer:\n{e}")
        return
        
    if action == "delete_flow":
        delete_torrent_flow()
        return

    if action == "download_file":
        link = params.get("link")
        if link:
            download_file_prompt(link)
        return

    if action == "play_local":
        play_local_downloads()
        return

    elif action == "clean_menu":
        show_clean_menu()
        return

    elif action == "rd_injector":
        from modules import rd_api_injector
        rd_api_injector.run_ui()
        return

    if action == "download_flow":
        torrents = api_get("/torrents") or []
        if not torrents:
            return
        names = [t.get("filename","Unknown") for t in torrents]
        idx = xbmcgui.Dialog().select("Choose torrent", names)
        if idx == -1:
            return
        cloud_files(torrents[idx].get("id"), mode="download")
        return

    if action == "account":
        account_info()
        return
        
    if action == "rd_diag_full":
        rd_full_diagnostics()
        return

    if action == "play_direct":
        url = params.get("url")
        if url:
            xbmc.Player().play(url)
        return

    if action == "export_import":
        from modules import export_import
        export_import.export_import_menu()
        return

    elif action == "play_rd_magnet":
        # Treat this as "add to cloud" now, NOT direct playback
        magnet = params.get("magnet")
        title  = params.get("title", "Unknown")
        if magnet:
            from modules import rdmagnet_importer
            ok = rdmagnet_importer.add_magnet(magnet)
            xbmcgui.Dialog().notification(
                "Real-Debrid",
                " Magnet sent to RD cloud" if ok else " Failed to add magnet",
                xbmcgui.NOTIFICATION_INFO if ok else xbmcgui.NOTIFICATION_ERROR,
                3000
            )
        else:
            xbmcgui.Dialog().ok("Real-Debrid", "Missing magnet link.")
        return

def show_multi_list():
    xbmcplugin.setPluginCategory(HANDLE, "Real-Debrid Cloud")
    xbmcplugin.setContent(HANDLE, "files")

    add_item("[COLOR green]==================[/COLOR]", {"action": "noop"}, False)
#    add_item(" Movie Genre Custom View", {"action": "custom_search"})
    add_item("Genre Last Viewed", {"action": "mag_browser_v4_w1"})
#    add_item("  Movie Year Custom View", {"action": "custom_search_year"})
    add_item("Year Last Viewed", {"action": "mag_browser_v4_w2"})
#    add_item("  Movie Decade Custom View", {"action": "custom_search_decade"})
    add_item("Decade Last Viewed", {"action": "mag_browser_v4_w3"})
#    add_item("  Movie A to Z Custom View", {"action": "custom_search_letters"})
    add_item("A to Z Last Viewed", {"action": "mag_browser_v4_w6"})
#    add_item("[COLOR gold]Experimental Not 100% Working[/COLOR]", {"action": "noop"}, False)  
#    add_item("  Movie Custom Multi View", {"action": "custom_search_combo"})
    add_item("Combo Multi Last Viewed", {"action": "mag_browser_v4_w5"})
    add_item("Search Last View", {"action": "mag_browser_v4_w4"})
   
    xbmcplugin.endOfDirectory(HANDLE)
     
def show_clean_menu():
    xbmcplugin.setPluginCategory(HANDLE, "Real-Debrid Cloud")
    xbmcplugin.setContent(HANDLE, "files")

     # ---------------- SEARCH ----------------
#    add_item("[COLOR gold]Search by Title or Plot[/COLOR]", {"action": "noop"}, False)
    add_item("Search Movies", {"action": "search_text"})
    add_item("Search Last View", {"action": "mag_browser_v4_w4"})
   
 # ---------------- RECENTLY ADDED ----------------    
#    add_item("[COLOR gold]Movies Recently Added[/COLOR]", {"action": "noop"}, False)     
    add_item("Recently Added", {"action": "mag_browser_v4_top_movies"})
#    add_item("[COLOR gray]not all search indexed[/COLOR]", {"action": "noop"}, False)   
   
    # ---------------- MOVIE LIST ----------------
#    add_item("[COLOR gold]Movies List De-duplicated[/COLOR]", {"action": "noop"}, False)      
    add_item("All Movies (Clean)", {"action": "all_movies_clean"}) 
    add_item("2025 (Clean)", {"action": "202x_movies_clean"}) 
    add_item("2024 (Clean)", {"action": "2024_movies_clean"}) 
    add_item("Years (Clean)", {"action": "sorted", "mode": "years"})
    add_item("Genres (Clean)", {"action": "sorted", "mode": "genres"})
    add_item("Decades (Clean)", {"action": "sorted", "mode": "decades"})
    add_item("A to Z (Clean)", {"action": "sorted", "mode": "letters"})    
    
   # ---------------- MULTI VIEW ----------------
#    add_item("[COLOR gold]Movie List Multi View[/COLOR]", {"action": "noop"}, False)    
    add_item("All Movies (Raw)", {"action": "mag_browser_v4_all"})
    add_item("Years Multi (Raw)", {"action": "custom_search_year"})
    add_item("Genres Multi (Raw)", {"action": "custom_search"})    
    add_item("Decades Multi (Raw)", {"action": "custom_search_decade"})  
    add_item("A to Z Multi (Raw)", {"action": "custom_search_letters"})
    add_item("Combo Multi (Raw)", {"action": "custom_search_combo"})
    
    # ---------------- Last Multi View ----------------   
#    add_item("[COLOR gold]Last Multi View[/COLOR]", {"action": "noop"}, False)
    add_item("View Last Multi (Raw)", {"action": "multi_list"})
    
    # ---------------- PLAYBACK ----------------
#    add_item("[COLOR gold]Play From[/COLOR]", {"action": "noop"}, False)
    add_item("Cloud", {"action": "cloud"})
    add_item("History", {"action": "history"})
    add_item("Local", {"action": "play_local"})

    # ---------------- CLOUD MANAGER ----------------
#    add_item("[COLOR gold]Cloud Manager[/COLOR]", {"action": "noop"}, False)
    add_item("Download", {"action": "download_flow"})
    add_item("Send Magnet", {"action": "add_magnet"})
    add_item("Delete Magnet", {"action": "delete_flow"})
    add_item("Unrestrict Link", {"action": "unrestrict_link"})

    # ---------------- RD STATUS ----------------
#    add_item("[COLOR gold]Real-Debrid Status[/COLOR]", {"action": "noop"}, False)
    add_item("RD Status", {"action": "account"})
    add_item("API Status", {"action": "rd_diag_full"})
    add_item("API Key Injector ", {"action": "rd_injector"})

    # ---------------- FILE MANAGEMENT ----------------
#    add_item("[COLOR gold]Manage Files & Folders[/COLOR]", {"action": "noop"}, False)
    add_item("Directory Tools", {"action": "export_import"})

    xbmcplugin.endOfDirectory(HANDLE)
        
# ------------------------ Entry ------------------------
if __name__ == "__main__":
    if HANDLE == -1:
        # script-safety (shouldnt happen for plugin, but guard anyway)
        show_root()
    else:
        router(sys.argv[2] if len(sys.argv) > 2 else "")
