import base64
import json
import re
import urllib.parse

import requests
import xbmc
import xbmcgui
import xbmcvfs

from tenbuttons_helpers import JET_GUIDE_IMPORTED_PATH

xbc = xbmc
xbcgui = xbmcgui
xbcvfs = xbmcvfs


def _handle_choice_multi(url, mpv_path, get_resolved_url, persist_resolved_streams, launch_multi_streams_mpv):
    header_dict = {}

    temp_file = xbcvfs.translatePath("special://temp/resolved_streams.json")
    resolved_streams = []

    # First resolve the current stream URL (handle plugin:// URLs)
    xbc.log(f"DEBUG: Play Multiple Streams - Starting with URL: {url}", level=xbc.LOGINFO)
    resolved_current_url, resolved_current_headers = get_resolved_url(url)
    xbc.log(f"DEBUG: Play Multiple Streams - Resolved URL: {resolved_current_url}", level=xbc.LOGINFO)
    xbc.log(f"DEBUG: Play Multiple Streams - Resolved Headers: {resolved_current_headers}", level=xbc.LOGINFO)

    if not resolved_current_url:
        resolved_current_url = url

    # Extract headers from resolved stream URL
    current_headers = resolved_current_headers.copy() if resolved_current_headers else {}
    check_url = resolved_current_url
    if resolved_current_url and '|' in resolved_current_url:
        url_parts = resolved_current_url.split('|', 1)
        check_url = url_parts[0]
        xbc.log(f"DEBUG: Play Multiple Streams - URL has pipe, extracted base URL: {check_url}", level=xbc.LOGINFO)
        try:
            header_string = url_parts[1]
            for header in header_string.split('&'):
                if '=' in header:
                    key, value = header.split('=', 1)
                    current_headers[key.lower()] = urllib.parse.unquote(value)
            xbc.log(f"DEBUG: Play Multiple Streams - Headers from URL pipe: {current_headers}", level=xbc.LOGINFO)
        except Exception as e:
            xbc.log(f"DEBUG: Error parsing headers from current stream: {str(e)}", level=xbc.LOGWARNING)

    xbc.log(f"DEBUG: Play Multiple Streams - Final check_url: {check_url}", level=xbc.LOGINFO)
    xbc.log(f"DEBUG: Play Multiple Streams - Final headers: {current_headers}", level=xbc.LOGINFO)

    try:
        xbc.log(f"DEBUG: Play Multiple Streams - Sending HEAD request to {check_url}", level=xbc.LOGINFO)
        response = requests.head(check_url, headers=current_headers, timeout=10, allow_redirects=True)
        xbc.log(f"DEBUG: Play Multiple Streams - HEAD response status: {response.status_code}", level=xbc.LOGINFO)
        if response.status_code == 200:
            xbc.log(f"DEBUG: Currently playing URL {check_url} is accessible", level=xbc.LOGINFO)
            resolved_streams.append({"url": check_url, "headers": current_headers, "title": "Currently Playing Stream"})
        else:
            xbc.log(f"DEBUG: Currently playing URL {check_url} returned status {response.status_code}", level=xbc.LOGWARNING)
            xbcgui.Dialog().ok("Error", f"Currently playing stream is not accessible: {check_url}. Status: {response.status_code}")
            return
    except Exception as e:
        xbc.log(f"DEBUG: Failed to access currently playing URL {check_url}: {str(e)}", level=xbc.LOGERROR)
        xbcgui.Dialog().ok("Error", f"Failed to access currently playing stream: {check_url}. Error: {str(e)}")
        return
    try:
        xbc.log(f"DEBUG: Attempting to read {JET_GUIDE_IMPORTED_PATH}", level=xbc.LOGINFO)
        if xbcvfs.exists(JET_GUIDE_IMPORTED_PATH):
            with xbcvfs.File(JET_GUIDE_IMPORTED_PATH, "r") as f:
                links = json.loads(f.read())
            xbc.log(f"DEBUG: Loaded {len(links)} entries from jet_guide_imported.json: {json.dumps(links, indent=2)}", level=xbc.LOGINFO)
        else:
            xbc.log(f"DEBUG: File {JET_GUIDE_IMPORTED_PATH} does not exist", level=xbc.LOGERROR)
            xbcgui.Dialog().ok("Error", f"No saved streams found at {JET_GUIDE_IMPORTED_PATH}.")
            return
    except Exception as e:
        xbc.log(f"DEBUG: Failed to load jet_guide_imported.json: {str(e)}", level=xbc.LOGERROR)
        xbcgui.Dialog().ok("Error", f"Failed to load saved streams: {str(e)}")
        return
    valid_links = [l for l in links if isinstance(l, dict) and "link" in l and (l["link"].startswith("http") or l["link"].endswith(".m3u8") or l["link"].startswith("plugin://"))]
    xbc.log(f"DEBUG: Found {len(valid_links)} valid streams after filtering", level=xbc.LOGINFO)
    if not valid_links:
        xbcgui.Dialog().ok("Error", f"No valid streams found in jet_guide_imported.json. Ensure streams have 'link' field with http, .m3u8, or plugin:// URLs.\n\nContents: {json.dumps(links, indent=2)}")
        return
    titles = [l.get("title", "Untitled Stream") for l in valid_links]
    selected_indices = xbcgui.Dialog().multiselect("Select ONE Additional Stream to Play", titles)
    if not selected_indices or len(selected_indices) != 1:
        xbcgui.Dialog().ok("Error", "You must select exactly one additional stream.")
        return
    for idx in selected_indices:
        plugin_url = valid_links[idx]["link"]
        stream_title = valid_links[idx].get("title", "Untitled Stream")
        xbc.log(f"DEBUG: Processing stream: {stream_title} ({plugin_url})", level=xbc.LOGINFO)
        if plugin_url.startswith("http") and (plugin_url.endswith(".m3u8") or plugin_url.endswith(".mp4") or plugin_url.endswith(".ts")):
            plugin_url = f"plugin://plugin.video.madtitansports/sportjetextractors/play?urls=direct://{plugin_url}"
            xbc.log(f"DEBUG: Wrapped HTTP URL as plugin URL: {plugin_url}", level=xbc.LOGINFO)
        resolved_url, resolved_headers = get_resolved_url(plugin_url)
        xbc.log(f"DEBUG: Stream '{stream_title}' original URL: {plugin_url}", level=xbc.LOGINFO)
        xbc.log(f"DEBUG: Stream '{stream_title}' resolved URL: {resolved_url}", level=xbc.LOGINFO)
        xbc.log(f"DEBUG: Stream '{stream_title}' resolved headers: {resolved_headers}", level=xbc.LOGINFO)

        # Try to extract actual stream URL from plugin parameters if it's a madtitansports link
        # We need to do this because Kodi's player.getPlayingFile() returns the same wrapper URL
        # for all channels from the same scraper, but the base64 data contains unique streams
        if plugin_url.startswith("plugin://plugin.video.madtitansports/play_video/"):
            try:
                # Extract base64 part from URL
                b64_part = plugin_url.split("/play_video/")[1]

                # Try standard base64 first, then URL-safe
                try:
                    decoded = base64.b64decode(b64_part).decode("utf-8")
                except:
                    try:
                        decoded = base64.urlsafe_b64decode(b64_part).decode("utf-8")
                    except:
                        decoded = None

                if decoded:
                    try:
                        data = json.loads(decoded)
                        xbc.log(f"DEBUG: Stream '{stream_title}' decoded base64 data: {json.dumps(data)[:500]}", level=xbc.LOGINFO)

                        # Check for sportjetextractors (array of URLs)
                        if "sportjetextractors" in data and data["sportjetextractors"]:
                            extracted_url = data["sportjetextractors"][0]
                            xbc.log(f"DEBUG: Found sportjetextractors URL: {extracted_url}", level=xbc.LOGINFO)
                            # Parse headers from the URL if it contains | headers
                            if "|" in extracted_url:
                                url_parts = extracted_url.split("|")
                                resolved_url = url_parts[0]
                                for part in url_parts[1:]:
                                    if "=" in part:
                                        k, v = part.split("=", 1)
                                        resolved_headers[k.lower()] = urllib.parse.unquote(v)
                            else:
                                resolved_url = extracted_url
                            xbc.log(f"DEBUG: Extracted unique URL with headers: {resolved_url}, {resolved_headers}", level=xbc.LOGINFO)
                        # Check for direct 'stream' key
                        elif "stream" in data and data["stream"] and str(data["stream"]).startswith("http"):
                            resolved_url = data["stream"]
                            xbc.log(f"DEBUG: Using 'stream' key URL: {resolved_url}", level=xbc.LOGINFO)
                        # Check for 'link' key (array)
                        elif "link" in data and isinstance(data["link"], list) and len(data["link"]) > 0:
                            link = data["link"][0]
                            if str(link).startswith("http"):
                                resolved_url = link
                                xbc.log(f"DEBUG: Using 'link' key URL: {resolved_url}", level=xbc.LOGINFO)
                            elif "urls=direct://" in str(link):
                                # Extract the direct URL from nested plugin URL
                                try:
                                    parsed = urllib.parse.urlparse(str(link))
                                    query = urllib.parse.parse_qs(parsed.query)
                                    if 'urls' in query:
                                        direct_url = query['urls'][0]
                                        if direct_url.startswith("direct://"):
                                            direct_url = direct_url.replace("direct://", "")
                                        resolved_url = direct_url
                                        xbc.log(f"DEBUG: Extracted direct URL from nested link: {resolved_url}", level=xbc.LOGINFO)
                                except Exception as e:
                                    xbc.log(f"DEBUG: Failed to extract direct URL: {str(e)}", level=xbc.LOGWARNING)
                        # Check for 'link' key (direct string) with nested plugin URL
                        elif "link" in data and isinstance(data["link"], str) and data["link"].startswith("plugin://"):
                            nested_link = data["link"]
                            xbc.log(f"DEBUG: 'link' is plugin URL: {nested_link}", level=xbc.LOGINFO)
                            if "urls=direct://" in nested_link:
                                try:
                                    parsed = urllib.parse.urlparse(nested_link)
                                    query = urllib.parse.parse_qs(parsed.query)
                                    if 'urls' in query:
                                        direct_url = query['urls'][0]
                                        if direct_url.startswith("direct://"):
                                            direct_url = direct_url.replace("direct://", "")
                                        resolved_url = direct_url
                                        xbc.log(f"DEBUG: Extracted direct URL from nested plugin: {resolved_url}", level=xbc.LOGINFO)
                                except Exception as e:
                                    xbc.log(f"DEBUG: Failed to extract direct URL: {str(e)}", level=xbc.LOGWARNING)
                            if not resolved_url:
                                # Try to resolve the nested plugin URL
                                xbc.log(f"DEBUG: Trying to resolve nested plugin URL: {nested_link}", level=xbc.LOGINFO)
                                nested_resolved, nested_headers = get_resolved_url(nested_link)
                                if nested_resolved and nested_resolved.startswith("http"):
                                    resolved_url = nested_resolved
                                    resolved_headers.update(nested_headers)
                                    xbc.log(f"DEBUG: Resolved nested plugin URL to: {resolved_url}", level=xbc.LOGINFO)
                    except json.JSONDecodeError as e:
                        xbc.log(f"DEBUG: Failed to parse JSON from decoded base64: {str(e)}", level=xbc.LOGWARNING)
            except Exception as e:
                xbc.log(f"DEBUG: Failed to extract stream from plugin URL: {str(e)}", level=xbc.LOGWARNING)

        if not resolved_url:
            xbc.log(f"DEBUG: Failed to resolve stream via playback: {stream_title}", level=xbc.LOGWARNING)
            fallback_url = None
            fallback_headers = {}
            if plugin_url.startswith("plugin://") and "/play_video/" in plugin_url:
                try:
                    b64 = plugin_url.split("/play_video/")[1]
                    decoded = base64.urlsafe_b64decode(b64).decode("utf-8")
                    data = json.loads(decoded)
                    if "sportjetextractors" in data and data["sportjetextractors"]:
                        fallback_url = data["sportjetextractors"][0]
                        fallback_headers = header_dict
                        xbc.log(f"DEBUG: Fallback to sportjetextractors URL: {fallback_url}", level=xbc.LOGINFO)
                    elif "link" in data and data["link"].startswith("http"):
                        fallback_url = data["link"]
                        fallback_headers = {}
                        if "|" in fallback_url:
                            fallback_url, headers_str = fallback_url.split("|", 1)
                            for part in headers_str.split("&"):
                                if "=" in part:
                                    k, v = part.split("=", 1)
                                    fallback_headers[k.lower()] = urllib.parse.unquote(v)
                        xbc.log(f"DEBUG: Fallback to link URL: {fallback_url}", level=xbc.LOGINFO)
                    if fallback_url and fallback_url.lower().endswith((".m3u8", ".mp4", ".ts")):
                        try:
                            response = requests.head(fallback_url, headers=fallback_headers or header_dict, timeout=5, allow_redirects=True)
                            if response.status_code == 200:
                                xbc.log(f"DEBUG: Fallback URL {fallback_url} is accessible and valid stream", level=xbc.LOGINFO)
                                resolved_url = fallback_url
                                resolved_headers = fallback_headers
                            else:
                                xbc.log(f"DEBUG: Fallback URL {fallback_url} returned status {response.status_code}", level=xbc.LOGWARNING)
                        except Exception as e:
                            xbc.log(f"DEBUG: Failed to access fallback URL {fallback_url}: {str(e)}", level=xbc.LOGERROR)
                except Exception as e:
                    xbc.log(f"DEBUG: Failed to decode plugin URL for fallback: {str(e)}", level=xbc.LOGWARNING)
            if not resolved_url:
                xbc.log(f"DEBUG: Prompting manual URL input for stream: {stream_title}", level=xbc.LOGINFO)
                manual_url = xbcgui.Dialog().input(f"Failed to resolve stream: {stream_title}\nEnter the stream URL manually (e.g., from VLC):", type=xbcgui.INPUT_ALPHANUM)
                if manual_url and manual_url.startswith("http") and manual_url.lower().endswith((".m3u8", ".mp4", ".ts")):
                    try:
                        response = requests.head(manual_url, headers=header_dict, timeout=5, allow_redirects=True)
                        if response.status_code == 200:
                            xbc.log(f"DEBUG: Manual URL {manual_url} is accessible", level=xbc.LOGINFO)
                            resolved_url = manual_url
                            resolved_headers = header_dict
                        else:
                            xbc.log(f"DEBUG: Manual URL {manual_url} returned status {response.status_code}", level=xbc.LOGWARNING)
                            xbcgui.Dialog().ok("Error", f"Manual URL is not accessible: {manual_url}. Status: {response.status_code}")
                            continue
                    except Exception as e:
                        xbc.log(f"DEBUG: Failed to access manual URL {manual_url}: {str(e)}", level=xbc.LOGERROR)
                        xbcgui.Dialog().ok("Error", f"Failed to access manual URL: {manual_url}. Error: {str(e)}")
                        continue
                else:
                    xbcgui.Dialog().ok("Error", f"Invalid or no URL provided for {stream_title}. Try playing it in VLC to verify.")
                    continue
        # Removed duplicate URL check - allow combining same URLs for PIP purposes
        # if resolved_url and resolved_url == check_url:
        #     xbc.log(f"DEBUG: Stream {stream_title} resolved to the same URL as current stream: {resolved_url}. Skipping duplicate.", level=xbc.LOGINFO)
        #     xbcgui.Dialog().ok("Duplicate Stream", f"Stream '{stream_title}' resolved to the same URL as the currently playing stream.\n\nThis usually means the scraper returned the same underlying stream for both channels.\n\nURL: {resolved_url}")
        #     continue
        if xbcgui.Dialog().yesno("Save Stream", f"Stream resolved: {resolved_url}\nSave to temporary file for multi-stream playback?"):
            resolved_streams.append({"url": resolved_url, "headers": resolved_headers, "title": stream_title})
            xbc.log(f"DEBUG: Saved resolved stream: {resolved_url}", level=xbc.LOGINFO)
        else:
            xbc.log(f"DEBUG: User chose not to save stream: {resolved_url}", level=xbc.LOGINFO)
    if not persist_resolved_streams(temp_file, resolved_streams):
        return
    launch_multi_streams_mpv(resolved_streams, mpv_path)
    return



def _handle_choice_multi_choose_source(url, mpv_path, get_resolved_url, persist_resolved_streams, launch_multi_streams_mpv):
    # Play Multiple Streams (Choose Source)
    source_choice = xbmcgui.Dialog().select("Select Source for Streams", ["Favorites", "Channel Listings"])
    if source_choice == -1:
        return
    temp_file = xbcvfs.translatePath("special://temp/resolved_streams.json")
    resolved_streams = []
    # First resolve the current stream URL (handle plugin:// URLs)
    xbc.log(f"DEBUG: Play Multiple Streams (Choose Source) - Starting with URL: {url}", level=xbc.LOGINFO)
    resolved_current_url, resolved_current_headers = get_resolved_url(url)
    xbc.log(f"DEBUG: Play Multiple Streams (Choose Source) - Resolved URL: {resolved_current_url}", level=xbc.LOGINFO)
    xbc.log(f"DEBUG: Play Multiple Streams (Choose Source) - Resolved Headers: {resolved_current_headers}", level=xbc.LOGINFO)
    if not resolved_current_url:
        resolved_current_url = url
    current_headers = resolved_current_headers.copy() if resolved_current_headers else {}
    check_url = resolved_current_url
    if resolved_current_url and '|' in resolved_current_url:
        url_parts = resolved_current_url.split('|', 1)
        check_url = url_parts[0]
        xbc.log(f"DEBUG: Play Multiple Streams (Choose Source) - URL has pipe, extracted base URL: {check_url}", level=xbc.LOGINFO)
        try:
            header_string = url_parts[1]
            for header in header_string.split('&'):
                if '=' in header:
                    key, value = header.split('=', 1)
                    current_headers[key.lower()] = urllib.parse.unquote(value)
            xbc.log(f"DEBUG: Play Multiple Streams (Choose Source) - Headers from URL pipe: {current_headers}", level=xbc.LOGINFO)
        except Exception as e:
            xbc.log(f"DEBUG: Error parsing headers from current stream: {str(e)}", level=xbc.LOGWARNING)
    xbc.log(f"DEBUG: Play Multiple Streams (Choose Source) - Final check_url: {check_url}", level=xbc.LOGINFO)
    xbc.log(f"DEBUG: Play Multiple Streams (Choose Source) - Final headers: {current_headers}", level=xbc.LOGINFO)
    try:
        xbc.log(f"DEBUG: Play Multiple Streams (Choose Source) - Sending HEAD request to {check_url}", level=xbc.LOGINFO)
        response = requests.head(check_url, headers=current_headers, timeout=10, allow_redirects=True)
        xbc.log(f"DEBUG: Play Multiple Streams (Choose Source) - HEAD response status: {response.status_code}", level=xbc.LOGINFO)
        if response.status_code == 200:
            xbc.log(f"DEBUG: Currently playing URL {check_url} is accessible", level=xbc.LOGINFO)
            resolved_streams.append({"url": check_url, "headers": current_headers, "title": "Currently Playing Stream"})
        else:
            xbc.log(f"DEBUG: Currently playing URL {check_url} returned status {response.status_code}", level=xbc.LOGWARNING)
            xbmcgui.Dialog().ok("Error", f"Currently playing stream is not accessible: {check_url}. Status: {response.status_code}")
            return
    except Exception as e:
        xbc.log(f"DEBUG: Failed to access currently playing URL {check_url}: {str(e)}", level=xbc.LOGERROR)
        xbmcgui.Dialog().ok("Error", f"Failed to access currently playing stream: {check_url}. Error: {str(e)}")
        return
    # Select additional streams from the chosen source
    if source_choice == 0:
        # Favorites
        try:
            xbc.log(f"DEBUG: Attempting to read {JET_GUIDE_IMPORTED_PATH}", level=xbc.LOGINFO)
            if xbcvfs.exists(JET_GUIDE_IMPORTED_PATH):
                with xbcvfs.File(JET_GUIDE_IMPORTED_PATH, "r") as f:
                    links = json.loads(f.read())
                xbc.log(f"DEBUG: Loaded {len(links)} entries from jet_guide_imported.json: {json.dumps(links, indent=2)}", level=xbc.LOGINFO)
            else:
                xbc.log(f"DEBUG: File {JET_GUIDE_IMPORTED_PATH} does not exist", level=xbc.LOGERROR)
                xbmcgui.Dialog().ok("Error", f"No saved streams found at {JET_GUIDE_IMPORTED_PATH}.")
                return
        except Exception as e:
            xbc.log(f"DEBUG: Failed to load jet_guide_imported.json: {str(e)}", level=xbc.LOGERROR)
            xbmcgui.Dialog().ok("Error", f"Failed to load saved streams: {str(e)}")
            return
        valid_links = [l for l in links if isinstance(l, dict) and "link" in l and (l["link"].startswith("http") or l["link"].endswith(".m3u8") or l["link"].startswith("plugin://"))]
        xbc.log(f"DEBUG: Found {len(valid_links)} valid streams after filtering", level=xbc.LOGINFO)
        if not valid_links:
            xbmcgui.Dialog().ok("Error", f"No valid streams found in jet_guide_imported.json. Ensure streams have 'link' field with http, .m3u8, or plugin:// URLs.\n\nContents: {json.dumps(links, indent=2)}")
            return
        titles = [l.get("title", "Untitled Stream") for l in valid_links]
        selected_indices = xbmcgui.Dialog().multiselect("Select ONE Additional Stream to Play", titles)
        if not selected_indices or len(selected_indices) != 1:
            xbmcgui.Dialog().ok("Error", "You must select exactly one additional stream.")
            return
        for idx in selected_indices:
            plugin_url = valid_links[idx]["link"]
            stream_title = valid_links[idx].get("title", "Untitled Stream")
            xbc.log(f"DEBUG: Processing stream: {stream_title} ({plugin_url})", level=xbc.LOGINFO)
            if plugin_url.startswith("http") and (plugin_url.endswith(".m3u8") or plugin_url.endswith(".mp4") or plugin_url.endswith(".ts")):
                plugin_url = f"plugin://plugin.video.madtitansports/sportjetextractors/play?urls=direct://{plugin_url}"
                xbc.log(f"DEBUG: Wrapped HTTP URL as plugin URL: {plugin_url}", level=xbc.LOGINFO)
            resolved_url, resolved_headers = get_resolved_url(plugin_url)
            xbc.log(f"DEBUG: Stream '{stream_title}' original URL: {plugin_url}", level=xbc.LOGINFO)
            xbc.log(f"DEBUG: Stream '{stream_title}' resolved URL: {resolved_url}", level=xbc.LOGINFO)
            xbc.log(f"DEBUG: Stream '{stream_title}' resolved headers: {resolved_headers}", level=xbc.LOGINFO)
            if not resolved_url:
                xbc.log(f"DEBUG: Failed to resolve stream via playback: {stream_title}", level=xbc.LOGWARNING)
                continue
            if xbcgui.Dialog().yesno("Save Stream", f"Stream resolved: {resolved_url}\nSave to temporary file for multi-stream playback?"):
                resolved_streams.append({"url": resolved_url, "headers": resolved_headers, "title": stream_title})
                xbc.log(f"DEBUG: Saved resolved stream: {resolved_url}", level=xbc.LOGINFO)
            else:
                xbc.log(f"DEBUG: User chose not to save stream: {resolved_url}", level=xbc.LOGINFO)
    elif source_choice == 1:
        # Channel Listings
        try:
            from channellist import get_channels
            channels = get_channels()
            valid_links = [c for c in channels if c.get("url") and (c["url"].startswith("http") or c["url"].endswith(".m3u8") or c["url"].startswith("plugin://"))]
            xbc.log(f"DEBUG: Found {len(valid_links)} valid channels after filtering", level=xbc.LOGINFO)
            if not valid_links:
                xbmcgui.Dialog().ok("Error", "No valid channels found in channel listings.")
                return
            titles = [c.get("name", "Untitled Channel") for c in valid_links]
            selected_indices = xbmcgui.Dialog().multiselect("Select ONE Additional Channel to Play", titles)
            if not selected_indices or len(selected_indices) != 1:
                xbmcgui.Dialog().ok("Error", "You must select exactly one additional channel.")
                return
            for idx in selected_indices:
                plugin_url = valid_links[idx]["url"]
                stream_title = valid_links[idx].get("name", "Untitled Channel")
                xbc.log(f"DEBUG: Processing channel: {stream_title} ({plugin_url})", level=xbc.LOGINFO)
                if plugin_url.startswith("http") and (plugin_url.endswith(".m3u8") or plugin_url.endswith(".mp4") or plugin_url.endswith(".ts")):
                    plugin_url = f"plugin://plugin.video.madtitansports/sportjetextractors/play?urls=direct://{plugin_url}"
                    xbc.log(f"DEBUG: Wrapped HTTP URL as plugin URL: {plugin_url}", level=xbc.LOGINFO)
                # Avoid resolving plugin URLs using player.getPlayingFile() if a stream is already playing
                if plugin_url.startswith("plugin://") and "search_json" in plugin_url:
                    parsed = urllib.parse.urlparse(plugin_url)
                    query = urllib.parse.parse_qs(parsed.query)
                    # Try to extract direct stream URL from 'urls' param
                    if 'urls' in query:
                        direct_url = query['urls'][0]
                        if direct_url.startswith("direct://"):
                            direct_url = direct_url.replace("direct://", "")
                        resolved_url = direct_url
                        resolved_headers = {}
                        xbc.log(f"DEBUG: Extracted direct URL from plugin param: {resolved_url}", level=xbc.LOGINFO)
                    else:
                        # If no direct URL, try to resolve using plugin playback (but warn if duplicate)
                        resolved_url, resolved_headers = get_resolved_url(plugin_url)
                        if resolved_url == check_url:
                            xbc.log(f"DEBUG: Duplicate stream detected for '{stream_title}': {resolved_url}", level=xbc.LOGWARNING)
                            choice = xbmcgui.Dialog().select(
                                "Duplicate detected. Choose an option:",
                                [
                                    f"Skip '{stream_title}' (default)",
                                    f"Manually enter a stream URL",
                                    f"Retry resolving plugin URL"
                                ]
                            )
                            if choice == 1:
                                manual_url = xbmcgui.Dialog().input("Enter stream URL (http(s) or .m3u8)")
                                if manual_url and manual_url.startswith("http"):
                                    resolved_url = manual_url
                                    resolved_headers = {}
                                    xbc.log(f"DEBUG: User manually entered stream URL: {resolved_url}", level=xbc.LOGINFO)
                                else:
                                    xbmcgui.Dialog().ok("Error", "Invalid manual URL entered.")
                                    continue
                            elif choice == 2:
                                resolved_url, resolved_headers = get_resolved_url(plugin_url)
                                xbc.log(f"DEBUG: Retried plugin URL resolution: {resolved_url}", level=xbc.LOGINFO)
                                if resolved_url == check_url:
                                    xbmcgui.Dialog().ok("Duplicate Stream", f"Retry still resolved to duplicate URL: {resolved_url}")
                                    continue
                            else:
                                xbmcgui.Dialog().ok("Duplicate Stream", f"Stream '{stream_title}' resolved to the same URL as the currently playing stream.\n\nThis usually means the scraper returned the same underlying stream for both channels.\n\nURL: {resolved_url}")
                                continue
                else:
                    resolved_url, resolved_headers = get_resolved_url(plugin_url)
                    if resolved_url == check_url:
                        xbc.log(f"DEBUG: Duplicate stream detected for '{stream_title}': {resolved_url}", level=xbc.LOGWARNING)
                        choice = xbmcgui.Dialog().select(
                            "Duplicate detected. Choose an option:",
                            [
                                f"Skip '{stream_title}' (default)",
                                f"Manually enter a stream URL",
                                f"Retry resolving plugin URL"
                            ]
                        )
                        if choice == 1:
                            manual_url = xbmcgui.Dialog().input("Enter stream URL (http(s) or .m3u8)")
                            if manual_url and manual_url.startswith("http"):
                                resolved_url = manual_url
                                resolved_headers = {}
                                xbc.log(f"DEBUG: User manually entered stream URL: {resolved_url}", level=xbc.LOGINFO)
                            else:
                                xbmcgui.Dialog().ok("Error", "Invalid manual URL entered.")
                                continue
                        elif choice == 2:
                            resolved_url, resolved_headers = get_resolved_url(plugin_url)
                            xbc.log(f"DEBUG: Retried plugin URL resolution: {resolved_url}", level=xbc.LOGINFO)
                            if resolved_url == check_url:
                                xbmcgui.Dialog().ok("Duplicate Stream", f"Retry still resolved to duplicate URL: {resolved_url}")
                                continue
                        else:
                            xbmcgui.Dialog().ok("Duplicate Stream", f"Stream '{stream_title}' resolved to the same URL as the currently playing stream.\n\nThis usually means the scraper returned the same underlying stream for both channels.\n\nURL: {resolved_url}")
                            continue
                xbc.log(f"DEBUG: Channel '{stream_title}' original URL: {plugin_url}", level=xbc.LOGINFO)
                xbc.log(f"DEBUG: Channel '{stream_title}' resolved URL: {resolved_url}", level=xbc.LOGINFO)
                xbc.log(f"DEBUG: Channel '{stream_title}' resolved headers: {resolved_headers}", level=xbc.LOGINFO)
                if not resolved_url or resolved_url.startswith("plugin://"):
                    xbc.log(f"DEBUG: Trying to extract stream URL from plugin JSON for: {stream_title}", level=xbc.LOGINFO)
                    try:
                        parsed = urllib.parse.urlparse(plugin_url)
                        query = urllib.parse.parse_qs(parsed.query)
                        if 'search_json' in plugin_url:
                            json_url = plugin_url.split('search_json/')[1].split('?')[0]
                            json_url = urllib.parse.unquote(json_url)
                            xbc.log(f"DEBUG: Fetching plugin JSON from: {json_url}", level=xbc.LOGINFO)
                            headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
                            response = requests.get(json_url, headers=headers, timeout=10)
                            xbc.log(f"DEBUG: JSON response status: {response.status_code}", level=xbc.LOGINFO)
                            if response.status_code == 200:
                                data = json.loads(response.text)
                                xbc.log(f"DEBUG: JSON data type: {type(data).__name__}, content: {str(data)[:500]}", level=xbc.LOGINFO)
                                items_to_check = []
                                extracted_sportjet_url = None
                                if isinstance(data, dict) and 'sportjetextractors' in data:
                                    sportjet_data = data['sportjetextractors']
                                    if isinstance(sportjet_data, list) and len(sportjet_data) > 0:
                                        sportjet_item = sportjet_data[0]
                                        if isinstance(sportjet_item, dict):
                                            sportjet_address = sportjet_item.get('address', '')
                                            if sportjet_address.startswith('jetproxy://'):
                                                match = re.search(r'jetproxy://(.+)', sportjet_address)
                                                if match:
                                                    extracted_sportjet_url = match.group(1)
                                                    xbc.log(f"DEBUG: Extracted sportjet jetproxy URL: {extracted_sportjet_url}", level=xbc.LOGINFO)
                                            elif sportjet_address.startswith('http'):
                                                extracted_sportjet_url = sportjet_address
                                                xbc.log(f"DEBUG: Extracted sportjet direct URL: {extracted_sportjet_url}", level=xbc.LOGINFO)
                                if isinstance(data, list) and len(data) > 0:
                                    items_to_check = data
                                elif isinstance(data, dict):
                                    xbc.log(f"DEBUG: JSON dict keys: {list(data.keys())}", level=xbc.LOGINFO)
                                    if 'items' in data and isinstance(data['items'], list):
                                        items_to_check = data['items']
                                    else:
                                        items_to_check = [data]
                                for item in items_to_check:
                                    xbc.log(f"DEBUG: JSON item keys: {list(item.keys()) if isinstance(item, dict) else 'not a dict'}", level=xbc.LOGINFO)
                                    link = item.get('link') or item.get('url') or item.get('stream_url') or item.get('play_url') or item.get('m3u8') or item.get('file') or item.get('address')
                                    if link:
                                        link_str = str(link)
                                        if link_str.startswith('plugin://'):
                                            if 'urls=ffmpegdirect://' in link_str:
                                                match = re.search(r'urls=ffmpegdirect://([^&]+)', link_str)
                                                if match:
                                                    resolved_url = match.group(1)
                                                    xbc.log(f"DEBUG: Extracted ffmpegdirect URL: {resolved_url}", level=xbc.LOGINFO)
                                                    break
                                            elif 'urls=direct://' in link_str:
                                                match = re.search(r'urls=direct://([^&]+)', link_str)
                                                if match:
                                                    resolved_url = match.group(1)
                                                    xbc.log(f"DEBUG: Extracted direct URL: {resolved_url}", level=xbc.LOGINFO)
                                                    break
                                            elif 'urls=jetproxy://' in link_str:
                                                match = re.search(r'urls=jetproxy://([^&]+)', link_str)
                                                if match:
                                                    resolved_url = match.group(1)
                                                    xbc.log(f"DEBUG: Extracted jetproxy URL: {resolved_url}", level=xbc.LOGINFO)
                                                    break
                                        elif link_str.startswith('jetproxy://'):
                                            match = re.search(r'jetproxy://(.+)', link_str)
                                            if match:
                                                resolved_url = match.group(1)
                                                xbc.log(f"DEBUG: Extracted jetproxy address: {resolved_url}", level=xbc.LOGINFO)
                                                break
                                        elif link_str.startswith('http'):
                                            resolved_url = link_str
                                            xbc.log(f"DEBUG: Extracted stream URL from plugin JSON: {resolved_url}", level=xbc.LOGINFO)
                                            break
                                if extracted_sportjet_url and not resolved_url:
                                    resolved_url = extracted_sportjet_url
                                    xbc.log(f"DEBUG: Using sportjet URL instead of channel guide URL: {resolved_url}", level=xbc.LOGINFO)
                    except Exception as e:
                        xbc.log(f"DEBUG: Failed to extract URL from plugin JSON: {str(e)}", level=xbc.LOGERROR)
                    if not resolved_url or resolved_url.startswith("plugin://"):
                        xbc.log(f"DEBUG: Cannot use channel '{stream_title}' - stream URL could not be extracted", level=xbc.LOGWARNING)
                        xbmcgui.Dialog().notification("Skipped", f"Channel '{stream_title}' - stream URL not available", xbmcgui.NOTIFICATION_WARNING, 3000)
                        continue
                proxy_match = re.match(r"http://127\.0\.0\.1:\d+\?url=(.+)", resolved_url)
                if proxy_match:
                    actual_url = proxy_match.group(1)
                    actual_url = urllib.parse.unquote(actual_url)
                    xbc.log(f"DEBUG: Extracted JetProxy URL to: {actual_url}", level=xbc.LOGINFO)
                    resolved_url = actual_url
                if xbcgui.Dialog().yesno("Save Channel", f"Channel resolved: {resolved_url}\nSave to temporary file for multi-stream playback?"):
                    resolved_streams.append({"url": resolved_url, "headers": resolved_headers, "title": stream_title})
                    xbc.log(f"DEBUG: Saved resolved channel: {resolved_url}", level=xbc.LOGINFO)
                else:
                    xbc.log(f"DEBUG: User chose not to save channel: {resolved_url}", level=xbc.LOGINFO)
        except Exception as e:
            xbc.log(f"DEBUG: Failed to load channels: {str(e)}", level=xbc.LOGERROR)
            xbmcgui.Dialog().ok("Error", f"Failed to load channels: {str(e)}")
            return
    if not persist_resolved_streams(temp_file, resolved_streams):
        return
    launch_multi_streams_mpv(resolved_streams, mpv_path)
    return
