import os
import random
import subprocess
import threading
import urllib.parse

import xbmc
import xbmcaddon
import xbmcgui

xbc = xbmc
xbcaddon = xbmcaddon
xbcgui = xbmcgui
ffmpeg_proc = None


def _handle_choice_record(url, is_android, mpv_path, ffmpeg_path, default_recording_path):
    global ffmpeg_proc

    headers = ""
    header_dict = {}

    # Use the already detected platform and paths
    folder_path = xbcaddon.Addon().getSetting("android_recording_path" if is_android else "recording_path")
    if not folder_path:
        folder_path = default_recording_path

    # For Android, try to create the directory if it doesn't exist
    if is_android and not os.path.isdir(folder_path):
        try:
            os.makedirs(folder_path, exist_ok=True)
            xbc.log(f"DEBUG: Created Android recording directory: {folder_path}", level=xbc.LOGINFO)
        except Exception as e:
            xbc.log(f"DEBUG: Failed to create Android recording directory {folder_path}: {str(e)}", level=xbc.LOGERROR)

    # If folder still doesn't exist or isn't accessible, prompt user
    if not folder_path or not os.path.isdir(folder_path):
        folder_path = xbcgui.Dialog().browse(0, "Select Output Folder", "files")
        if not folder_path:
            xbc.log(f"DEBUG: No folder selected for recording", level=xbc.LOGINFO)
            return

    filename = xbcgui.Dialog().input("Enter filename (e.g. recorded.ts)", type=xbcgui.INPUT_ALPHANUM)
    if not filename:
        xbc.log(f"DEBUG: No filename provided for recording", level=xbc.LOGINFO)
        return
    if not filename.lower().endswith(".ts"):
        filename += ".ts"
    output_path = os.path.join(folder_path, filename)

    # Handle file overwrite with Kodi dialog
    if os.path.exists(output_path):
        if not xbcgui.Dialog().yesno("Overwrite File", f"File '{filename}' already exists. Overwrite it?"):
            xbc.log(f"DEBUG: User chose not to overwrite file {output_path}", level=xbc.LOGINFO)
            return
        try:
            os.remove(output_path)
            xbc.log(f"DEBUG: Deleted existing file {output_path}", level=xbc.LOGINFO)
        except Exception as e:
            xbc.log(f"DEBUG: Failed to delete existing file {output_path}: {str(e)}", level=xbc.LOGERROR)
            xbcgui.Dialog().ok("Error", f"Cannot overwrite {filename}: {str(e)}")
            return

    # Verify folder is writable
    try:
        temp_file = os.path.join(folder_path, f"test_{random.randint(1000,9999)}.tmp")
        with open(temp_file, 'w') as f:
            f.write("test")
        os.remove(temp_file)
    except Exception as e:
        xbc.log(f"DEBUG: Output folder {folder_path} is not writable: {str(e)}", level=xbc.LOGERROR)
        xbcgui.Dialog().ok("Error", f"Cannot write to folder: {str(e)}")
        return

    if is_android:
        # Android recording using mpv through Termux
        xbc.log(f"DEBUG: Android detected, using mpv for recording", level=xbc.LOGINFO)
        xbc.log(f"DEBUG: Using mpv path: {mpv_path}", level=xbc.LOGINFO)

        # Find mpv executable on Android/Termux
        def find_android_mpv():
            # Show debug info via notifications instead of logs
            xbcgui.Dialog().notification("Debug", f"Starting mpv search...", xbcgui.NOTIFICATION_INFO, 2000)

            # Common Termux paths for mpv
            possible_paths = [
                "/data/data/com.termux/files/usr/bin/mpv",
                "/system/bin/mpv",
                "/system/xbin/mpv",
                "/data/data/com.termux/files/usr/local/bin/mpv",
                mpv_path  # User-specified path
            ]

            # Try to use 'which' command to find mpv
            try:
                which_result = subprocess.run(["which", "mpv"], capture_output=True, text=True, timeout=5)
                if which_result.returncode == 0 and which_result.stdout.strip():
                    which_path = which_result.stdout.strip()
                    possible_paths.insert(0, which_path)  # Add to front of list
                    xbcgui.Dialog().notification("Debug", f"which found: {which_path}", xbcgui.NOTIFICATION_INFO, 3000)
            except Exception as e:
                xbcgui.Dialog().notification("Debug", f"which failed: {str(e)}", xbcgui.NOTIFICATION_ERROR, 3000)

            # Try each possible path
            tested_paths = []
            for test_path in possible_paths:
                if not test_path:
                    continue
                tested_paths.append(test_path)
                try:
                    test_proc = subprocess.run([test_path, "--version"], capture_output=True, text=True, timeout=5)
                    if test_proc.returncode == 0:
                        xbcgui.Dialog().notification("Debug", f"Found working: {test_path}", xbcgui.NOTIFICATION_INFO, 4000)
                        return test_path
                except FileNotFoundError:
                    xbcgui.Dialog().notification("Debug", f"Not found: {test_path}", xbcgui.NOTIFICATION_WARNING, 2000)
                except Exception as e:
                    xbcgui.Dialog().notification("Debug", f"Error at {test_path}: {str(e)}", xbcgui.NOTIFICATION_ERROR, 3000)

            # Show all tested paths if nothing worked
            all_paths = "\n".join(tested_paths[:3])  # Show first 3 paths
            xbcgui.Dialog().ok("mpv Search Results", f"Tested paths:\n{all_paths}\n\nNone worked. Try manually setting the path in Android settings.")
            return None

        # Find working mpv path
        working_mpv_path = find_android_mpv()
        if not working_mpv_path:
            return

        # Update mpv_path to the working path
        mpv_path = working_mpv_path

        # Build mpv recording command for Android/Termux
        mpv_command = [
            mpv_path,
            "--no-video",  # Don't display video during recording
            "--ao=null",   # No audio output during recording
            "--stream-record=" + output_path,
            "--no-terminal",  # Reduce terminal output
            "--msg-level=all=warn",  # Reduce log verbosity
            "--idle=no",   # Exit when done
        ]

        # Add headers if present
        if headers:
            # Format headers properly for mpv
            header_list = []
            for k, v in header_dict.items():
                if k.lower() in ["referer", "user-agent", "origin"]:
                    header_list.append(f"{k}: {v}")
            if header_list:
                mpv_command.extend(["--http-header-fields=" + ",".join(header_list)])

        # Add the stream URL
        mpv_command.append(url)

        xbc.log(f"DEBUG: Launching mpv recording with command: {' '.join(mpv_command)}", level=xbc.LOGINFO)

        try:
            # Use Termux-compatible process creation
            ffmpeg_proc = subprocess.Popen(
                mpv_command,
                stdin=subprocess.DEVNULL,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True
            )
            xbc.log(f"DEBUG: mpv recording process started with PID: {ffmpeg_proc.pid}", level=xbc.LOGINFO)
            xbcgui.Dialog().notification("Record", f"Recording started: {filename}\nUsing mpv on Android", xbcgui.NOTIFICATION_INFO, 3000)

            # Monitor process for Android
            def monitor_android_recording():
                global ffmpeg_proc
                try:
                    stdout, stderr = ffmpeg_proc.communicate(timeout=None)
                    exit_code = ffmpeg_proc.returncode if ffmpeg_proc is not None else 'unknown'
                    if ffmpeg_proc is not None and exit_code == 0 and os.path.exists(output_path) and os.path.getsize(output_path) > 0:
                        xbc.log(f"DEBUG: Android recording completed successfully: {output_path}", level=xbc.LOGINFO)
                        xbcgui.Dialog().notification("Record", f"Recording completed: {filename}", xbcgui.NOTIFICATION_INFO, 5000)
                    else:
                        xbc.log(f"DEBUG: mpv recording failed with exit code {exit_code}", level=xbc.LOGERROR)
                        xbc.log(f"DEBUG: mpv stderr: {stderr}", level=xbc.LOGERROR)
                        xbcgui.Dialog().notification("Record", f"Recording failed: Exit code {exit_code}", xbcgui.NOTIFICATION_ERROR, 5000)
                except Exception as e:
                    xbc.log(f"DEBUG: Error monitoring mpv recording process: {str(e)}", level=xbc.LOGERROR)
                    xbcgui.Dialog().notification("Record", f"Recording error: {str(e)}", xbcgui.NOTIFICATION_ERROR, 5000)
                finally:
                    ffmpeg_proc = None  # Reset after completion
            threading.Thread(target=monitor_android_recording, daemon=True).start()

        except Exception as e:
            xbc.log(f"DEBUG: Failed to launch mpv recording: {str(e)}", level=xbc.LOGERROR)
            xbcgui.Dialog().ok("Error", f"Failed to launch mpv recording: {str(e)}")

    else:
        # PC recording using ffmpeg (existing code)
        xbc.log(f"DEBUG: PC detected, using ffmpeg for recording", level=xbc.LOGINFO)

        # Verify ffmpeg exists
        if not os.path.isfile(ffmpeg_path):
            xbc.log(f"DEBUG: ffmpeg not found at {ffmpeg_path}", level=xbc.LOGERROR)
            xbcgui.Dialog().ok("Error", f"ffmpeg not found at {ffmpeg_path}")
            return

        # Build ffmpeg command
        # Extract headers from url if present
        ffmpeg_headers = ""
        ffmpeg_url = url
        header_string = ""
        if "|" in url:
            ffmpeg_url, header_string = url.split("|", 1)
            header_lines = []
            for header in header_string.split("&"):
                if "=" in header:
                    k, v = header.split("=", 1)
                    # Remove quotes, ensure proper line endings, and strip trailing slash for Referer/Origin
                    clean_v = urllib.parse.unquote(v)
                    if k.lower() in ["referer", "origin"] and clean_v.endswith("/"):
                        clean_v = clean_v[:-1]
                    header_lines.append(f"{k}: {clean_v}\\r\\n")
            if header_lines:
                ffmpeg_headers = "".join(header_lines)
        ffmpeg_command = [
            ffmpeg_path,
            "-loglevel", "verbose",
        ]
        if ffmpeg_headers:
            ffmpeg_command += ["-headers", ffmpeg_headers]
        # Add explicit user_agent and referer flags if present
        for k, v in [("user-agent", None), ("referer", None)]:
            for header in header_string.split("&"):
                if "=" in header:
                    hk, hv = header.split("=", 1)
                    if hk.lower() == k:
                        clean_v = urllib.parse.unquote(hv)
                        if k == "user-agent":
                            ffmpeg_command += ["-user_agent", clean_v]
                        elif k == "referer":
                            ffmpeg_command += ["-referer", clean_v]
        ffmpeg_command += [
            "-i", ffmpeg_url,
            "-c:v", "copy",
            "-c:a", "copy",
            "-f", "mpegts",
            output_path
        ]
        xbc.log(f"DEBUG: Launching ffmpeg with command: {' '.join(ffmpeg_command)}", level=xbc.LOGINFO)
        CREATE_NEW_CONSOLE = 0x00000010
        try:
            ffmpeg_proc = subprocess.Popen(
                ffmpeg_command,
                creationflags=0x00000010
            )
            xbc.log(f"DEBUG: ffmpeg process started with PID: {ffmpeg_proc.pid}", level=xbc.LOGINFO)
            xbcgui.Dialog().notification("Record", f"Recording started: {filename}\nCheck console for progress", xbcgui.NOTIFICATION_INFO, 3000)

            # Monitor process
            def monitor_process():
                global ffmpeg_proc
                try:
                    stdout, stderr = ffmpeg_proc.communicate()
                    exit_code = ffmpeg_proc.returncode if ffmpeg_proc is not None else 'unknown'
                    if ffmpeg_proc is not None and exit_code == 0 and os.path.exists(output_path) and os.path.getsize(output_path) > 0:
                        xbc.log(f"DEBUG: Recording completed successfully: {output_path}", level=xbc.LOGINFO)
                        xbcgui.Dialog().notification("Record", f"Recording completed: {filename}", xbcgui.NOTIFICATION_INFO, 5000)
                    else:
                        xbc.log(f"DEBUG: ffmpeg process failed with exit code {exit_code}", level=xbc.LOGERROR)
                        xbc.log(f"DEBUG: ffmpeg stdout: {stdout}", level=xbc.LOGERROR)
                        xbc.log(f"DEBUG: ffmpeg stderr: {stderr}", level=xbc.LOGERROR)
                        error_msg = "ffmpeg failed:\n"
                        if stderr:
                            error_msg += stderr
                        elif stdout:
                            error_msg += stdout
                        else:
                            error_msg += "No error output. Try running the command manually in a terminal for more details."
                        xbcgui.Dialog().ok("ffmpeg Error Output", error_msg)
                except Exception as e:
                    xbc.log(f"DEBUG: Error monitoring ffmpeg process: {str(e)}", level=xbc.LOGERROR)
                    xbcgui.Dialog().notification("Record", f"Recording error: {str(e)}", xbcgui.NOTIFICATION_ERROR, 5000)
                finally:
                    ffmpeg_proc = None  # Reset after completion
            threading.Thread(target=monitor_process, daemon=True).start()
        except Exception as e:
            xbc.log(f"DEBUG: Failed to launch ffmpeg: {str(e)}", level=xbc.LOGERROR)
            xbcgui.Dialog().ok("Error", f"Failed to launch ffmpeg: {str(e)}")
    return



def _handle_choice_stop_recording():
    global ffmpeg_proc

    try:
        if ffmpeg_proc and ffmpeg_proc.poll() is None:
            ffmpeg_proc.terminate()
            try:
                ffmpeg_proc.wait(timeout=5)
                xbc.log(f"DEBUG: ffmpeg process (PID: {ffmpeg_proc.pid}) terminated successfully", level=xbc.LOGINFO)
                xbcgui.Dialog().notification("Record", "Recording stopped.", xbcgui.NOTIFICATION_INFO, 3000)
            except subprocess.TimeoutExpired:
                ffmpeg_proc.kill()
                xbc.log(f"DEBUG: ffmpeg process (PID: {ffmpeg_proc.pid}) forcibly killed after timeout", level=xbc.LOGWARNING)
                xbcgui.Dialog().notification("Record", "Recording forcibly stopped.", xbcgui.NOTIFICATION_INFO, 3000)
            ffmpeg_proc = None
        else:
            xbc.log(f"DEBUG: No active ffmpeg process to stop", level=xbc.LOGINFO)
            xbcgui.Dialog().notification("Record", "No active recording to stop.", xbcgui.NOTIFICATION_INFO, 3000)
    except Exception as e:
        xbc.log(f"DEBUG: Error stopping ffmpeg process: {str(e)}", level=xbc.LOGERROR)
        xbcgui.Dialog().notification("Record", f"Error stopping recording: {str(e)}", xbcgui.NOTIFICATION_ERROR, 3000)
    return



def _handle_choice_watch_recording():
    # Watch Recording
    folder_path = xbmcaddon.Addon().getSetting("recording_path")
    if not folder_path or not os.path.isdir(folder_path):
        xbcgui.Dialog().ok("Error", "Recording path is not set or invalid.")
        return
    files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
    if not files:
        xbcgui.Dialog().ok("Error", "No recordings found in the folder.")
        return
    idx = xbcgui.Dialog().select("Select Recording to Play", files)
    if idx == -1:
        return
    file_to_play = os.path.join(folder_path, files[idx])
    xbmc.Player().play(file_to_play)
    xbcgui.Dialog().notification("Kodi", f"Playing: {files[idx]}", xbcgui.NOTIFICATION_INFO, 3000)
    return
