import json
import os
import xml.etree.ElementTree as ET

import xbmc
import xbmcaddon
import xbmcgui
import xbmcvfs

from epggrid_mpv import launch_mpv_for_current_channel
from tools import debug_log, manage_custom_groups
from tools_links import browse_addon_plugin_folders, browse_installed_video_addons


def _cancel_youtube_playback_safe():
    try:
        from youtube_guide import cancel_youtube_playback

        cancel_youtube_playback()
    except ImportError:
        pass
    except Exception as e:
        debug_log(f"DEBUG: Error stopping YouTube playlist: {str(e)}", xbmc.LOGERROR)


def _play_link(link):
    if isinstance(link, list):
        link = link[0] if link else ""
    if not isinstance(link, str):
        return False, link
    if link.startswith("plugin://"):
        xbmc.executebuiltin(f'PlayMedia("{link}")')
        return True, link
    if link.startswith("http") or link.endswith(".m3u8"):
        _cancel_youtube_playback_safe()
        xbmc.Player().play(link)
        return True, link
    return False, link


def _play_from_imported():
    profile_path = xbmcvfs.translatePath(xbmcaddon.Addon().getAddonInfo('profile'))
    save_path = profile_path + "jet_guide_imported.json"
    if not xbmcvfs.exists(save_path):
        xbmcgui.Dialog().ok('Jet Guide', 'No imported channels saved.')
        return

    with xbmcvfs.File(save_path, 'r') as f:
        imported = json.loads(f.read())
    if not imported:
        xbmcgui.Dialog().ok('Jet Guide', 'No imported channels saved.')
        return

    titles = [c.get('title', 'Unknown') for c in imported]
    idx = xbmcgui.Dialog().select('Play Imported Channel', titles)
    if idx < 0:
        return

    link = imported[idx].get('link')
    ok, resolved = _play_link(link)
    if not ok:
        debug_log(f"JetGuide DEBUG: Not playable (EPGGrid). Link: {resolved}", xbmc.LOGERROR)
        xbmcgui.Dialog().ok("Error", f"This link is not a direct playable stream.\n\nLink: {resolved}")


def _play_from_folder():
    profile_path = xbmcvfs.translatePath(xbmcaddon.Addon().getAddonInfo('profile'))
    folders_base = os.path.join(profile_path, "jet_guide_folders")
    try:
        folders = [f for f in os.listdir(folders_base) if os.path.isdir(os.path.join(folders_base, f))]
    except Exception as e:
        debug_log(f"DEBUG: os.listdir failed for {folders_base}: {e}", xbmc.LOGERROR)
        folders = []

    if not folders:
        xbmcgui.Dialog().ok('Jet Guide', 'No folders found.')
        return

    folder_idx = xbmcgui.Dialog().select('Select Folder', folders)
    if folder_idx < 0:
        return

    folder_path = os.path.join(folders_base, folders[folder_idx])
    links_file = os.path.join(folder_path, "links.json")
    if not os.path.exists(links_file):
        xbmcgui.Dialog().ok('Jet Guide', 'No links.json found in folder.')
        return

    with open(links_file, "r", encoding="utf-8") as f:
        links = json.load(f)
    if not links:
        xbmcgui.Dialog().ok('Jet Guide', 'No links found in folder.')
        return

    titles = [c.get('title', 'Unknown') for c in links]
    idx = xbmcgui.Dialog().select('Play Folder Link', titles)
    if idx < 0:
        return

    link = links[idx].get('link')
    ok, resolved = _play_link(link)
    if not ok:
        debug_log(f"JetGuide DEBUG: Not playable (EPGGrid). Link: {resolved}", xbmc.LOGERROR)
        xbmcgui.Dialog().ok("Error", f"This link is not a direct playable stream.\n\nLink: {resolved}")


def _save_playing_stream(channel):
    player = xbmc.Player()
    if not player.isPlaying():
        xbmcgui.Dialog().notification('Error', 'No stream is currently playing', xbmcgui.NOTIFICATION_ERROR, 3000)
        return

    playing_file = player.getPlayingFile()
    debug_log(f"DEBUG: Saving currently playing stream: {playing_file}", xbmc.LOGINFO)
    if not playing_file:
        jsonrpc_request = {
            'jsonrpc': '2.0',
            'method': 'Player.GetItem',
            'params': {'playerid': 1},
            'id': 1,
        }
        result = xbmc.executeJSONRPC(json.dumps(jsonrpc_request))
        data = json.loads(result)
        playing_file = data.get('result', {}).get('item', {}).get('file', '')
        debug_log(f"DEBUG: Got playing file from JSON-RPC: {playing_file}", xbmc.LOGINFO)

    if not playing_file:
        xbmcgui.Dialog().notification('Error', 'Could not get playing stream URL', xbmcgui.NOTIFICATION_ERROR, 3000)
        return

    suggested_name = channel.get('name', 'Saved Stream') if isinstance(channel, dict) else 'Saved Stream'
    name = xbmcgui.Dialog().input('Enter a name for this stream', defaultt=suggested_name)
    if not name:
        xbmcgui.Dialog().notification('Cancelled', 'No name entered', xbmcgui.NOTIFICATION_INFO, 2000)
        return

    xbmc.sleep(100)
    save_options = ["Jet Guide Imported", "Saved Folder"]
    choice = xbmcgui.Dialog().select("Save To", save_options)
    if choice == -1:
        xbmcgui.Dialog().notification('Cancelled', 'Save cancelled', xbmcgui.NOTIFICATION_INFO, 2000)
        return

    if choice == 0:
        profile_path = xbmcvfs.translatePath(xbmcaddon.Addon().getAddonInfo('profile'))
        save_path = profile_path + "jet_guide_imported.json"
        imported = []
        if xbmcvfs.exists(save_path):
            with xbmcvfs.File(save_path, 'r') as f:
                imported = json.loads(f.read())
        imported.append({'title': name, 'link': playing_file})
        with xbmcvfs.File(save_path, 'w') as f:
            f.write(json.dumps(imported, indent=2, ensure_ascii=False))
        xbmcgui.Dialog().notification('Saved', f'Stream "{name}" saved to Imported', xbmcgui.NOTIFICATION_INFO, 2000)
        return

    folders_base_path = "special://userdata/addon_data/plugin.video.jet_guide/jet_guide_folders"
    folders_base = xbmcvfs.translatePath(folders_base_path)
    try:
        folders = [f for f in os.listdir(folders_base) if os.path.isdir(os.path.join(folders_base, f))]
    except Exception:
        folders = []

    if not folders:
        if xbmcgui.Dialog().yesno("No Folders Found", "Would you like to create a new folder?"):
            folder_name = xbmcgui.Dialog().input("Enter folder name")
            if folder_name:
                new_folder_path = os.path.join(folders_base, folder_name)
                try:
                    os.makedirs(new_folder_path, exist_ok=True)
                    links_file = os.path.join(new_folder_path, "links.json")
                    with open(links_file, "w", encoding="utf-8") as f:
                        json.dump([{"title": name, "link": playing_file}], f, indent=2)
                    xbmcgui.Dialog().notification('Saved', f'Stream "{name}" saved to folder "{folder_name}"', xbmcgui.NOTIFICATION_INFO, 2000)
                except Exception as e:
                    xbmcgui.Dialog().notification('Error', f'Failed to create folder: {e}', xbmcgui.NOTIFICATION_ERROR, 3000)
        return

    folder_options = folders + ["[Create New Folder]"]
    folder_idx = xbmcgui.Dialog().select('Select Folder', folder_options)
    if folder_idx < 0:
        return

    if folder_idx == len(folders):
        folder_name = xbmcgui.Dialog().input("Enter folder name")
        if folder_name:
            new_folder_path = os.path.join(folders_base, folder_name)
            try:
                os.makedirs(new_folder_path, exist_ok=True)
                links_file = os.path.join(new_folder_path, "links.json")
                with open(links_file, "w", encoding="utf-8") as f:
                    json.dump([{"title": name, "link": playing_file}], f, indent=2)
                xbmcgui.Dialog().notification('Saved', f'Stream "{name}" saved to folder "{folder_name}"', xbmcgui.NOTIFICATION_INFO, 2000)
            except Exception as e:
                xbmcgui.Dialog().notification('Error', f'Failed to create folder: {e}', xbmcgui.NOTIFICATION_ERROR, 3000)
        return

    folder_path = os.path.join(folders_base, folders[folder_idx])
    links_file = os.path.join(folder_path, "links.json")
    if os.path.exists(links_file):
        with open(links_file, "r", encoding="utf-8") as f:
            folder_links = json.load(f)
    else:
        folder_links = []
    folder_links.append({"title": name, "link": playing_file})
    with open(links_file, "w", encoding="utf-8") as f:
        json.dump(folder_links, f, indent=2)
    xbmcgui.Dialog().notification('Saved', f'Stream "{name}" saved to folder "{folders[folder_idx]}"', xbmcgui.NOTIFICATION_INFO, 2000)


def _save_to_kodi_favorites(channel):
    player = xbmc.Player()
    if not player.isPlaying():
        xbmcgui.Dialog().notification('Error', 'No stream is currently playing', xbmcgui.NOTIFICATION_ERROR, 3000)
        return

    playing_file = player.getPlayingFile()
    debug_log(f"DEBUG: Saving to Kodi favorites: {playing_file}", xbmc.LOGINFO)
    if not playing_file:
        jsonrpc_request = {
            'jsonrpc': '2.0',
            'method': 'Player.GetItem',
            'params': {'playerid': 1},
            'id': 1,
        }
        result = xbmc.executeJSONRPC(json.dumps(jsonrpc_request))
        data = json.loads(result)
        playing_file = data.get('result', {}).get('item', {}).get('file', '')
        debug_log(f"DEBUG: Got playing file from JSON-RPC: {playing_file}", xbmc.LOGINFO)

    if not playing_file:
        xbmcgui.Dialog().notification('Error', 'Could not get playing stream URL', xbmcgui.NOTIFICATION_ERROR, 3000)
        return

    suggested_name = channel.get('name', 'Saved Stream') if isinstance(channel, dict) else 'Saved Stream'
    name = xbmcgui.Dialog().input('Enter a name for Kodi favorite', defaultt=suggested_name)
    if not name:
        xbmcgui.Dialog().notification('Cancelled', 'No name entered', xbmcgui.NOTIFICATION_INFO, 2000)
        return

    fav_path = xbmcvfs.translatePath("special://userdata/favourites.xml")
    if xbmcvfs.exists(fav_path):
        try:
            tree = ET.parse(fav_path)
            root = tree.getroot()
        except Exception:
            root = ET.Element('favourites')
    else:
        root = ET.Element('favourites')

    fav_element = ET.SubElement(root, 'favourite', name=name)
    fav_element.text = f'PlayMedia("{playing_file}")'
    tree = ET.ElementTree(root)
    tree.write(fav_path, encoding='utf-8', xml_declaration=True)
    xbmcgui.Dialog().notification('Saved', f'"{name}" added to Kodi Favorites', xbmcgui.NOTIFICATION_INFO, 2000)


def show_context_menu(window, channel):
    from favorites import favorites_manager
    from ai_assistant import is_enabled as ai_enabled

    options = []
    if favorites_manager.is_favorite(channel['tvg_id']):
        options.append(('Remove from Favorites', 'remove'))
    else:
        options.append(('Add to Favorites', 'add'))
    options.append(('Return to Video Player', 'return_video'))
    options.append(('Play Channel', 'play'))
    options.append(('Play from Jet Guide Imported', 'play_imported'))
    options.append(('Play from Folder', 'play_from_folder'))
    options.append(('Stop YouTube Playlist', 'stop_youtube'))
    options.append(('Set Reminder for Current Program', 'remind'))
    options.append(('Show All Reminders', 'show_reminders'))
    options.append(('Search Addons', 'search_addons'))
    options.append(('Play Stream in mpv', 'mpv'))
    options.append(('Create Custom Channel Group', 'create_custom_group'))
    options.append(('Manage Custom Groups', 'manage_custom_groups'))

    if ai_enabled():
        options.append(('AI Assistant', 'ai_assistant'))

    player = xbmc.Player()
    if player.isPlaying():
        options.append(('Save Stream to Jet Guide', 'save_playing_stream'))
        options.append(('Save Stream to Kodi Favorites', 'save_to_kodi_favorites'))
        try:
            from jet_pip import is_pip_running
            debug_log("DEBUG: jet_pip imported successfully, is_pip_running=%s" % str(is_pip_running()), xbmc.LOGINFO)
            if is_pip_running():
                options.append(('Stop Picture-in-Picture', 'pip_stop'))
            else:
                options.append(('Picture-in-Picture', 'pip_start'))
        except Exception as e:
            debug_log("DEBUG: jet_pip not available: %s" % str(e), xbmc.LOGWARNING)
            import traceback
            debug_log("DEBUG: jet_pip error: %s" % traceback.format_exc(), xbmc.LOGWARNING)

    debug_log("DEBUG: Context menu options: %s" % [o[0] for o in options], xbmc.LOGINFO)

    choice = xbmcgui.Dialog().select('Channel Options', [option[0] for option in options])
    if choice < 0:
        return

    action = options[choice][1]
    if action == 'play':
        window.play_selected_channel()
    elif action == 'add':
        if favorites_manager.add_favorite(channel['tvg_id']):
            xbmcgui.Dialog().notification('Favorites', f'Added {channel["name"]} to favorites', xbmcgui.NOTIFICATION_INFO, 2000)
    elif action == 'remove':
        favorites_manager.remove_favorite(channel['tvg_id'])
        xbmcgui.Dialog().notification('Favorites', f'Removed {channel["name"]} from favorites', xbmcgui.NOTIFICATION_INFO, 2000)
    elif action == 'stop_youtube':
        _cancel_youtube_playback_safe()
        xbmcgui.Dialog().notification('YouTube Playlist', 'Playlist stopped', xbmcgui.NOTIFICATION_INFO, 2000)
    elif action == 'mpv':
        try:
            channel_idx = window.channels.index(channel)
            window.current_channel_idx = channel_idx
        except Exception:
            pass
        launch_mpv_for_current_channel(window)
    elif action == 'play_imported':
        _play_from_imported()
    elif action == 'play_from_folder':
        _play_from_folder()
    elif action == 'remind':
        channel_name = channel.get('name', 'Unknown') if isinstance(channel, dict) else str(channel)
        window.update_selected_program_info()
        program_title = window.getProperty('ProgramTitle')
        slot_idx = window.time_scroll_pos
        slot_start, _slot_end = window.time_slots[slot_idx]
        from reminders import add_reminder

        add_reminder(channel_name, program_title, int(slot_start.timestamp()))
        xbmcgui.Dialog().notification('Reminder', f'Reminder set for {program_title}', xbmcgui.NOTIFICATION_INFO, 2000)
    elif action == 'show_reminders':
        from reminders import list_reminders

        xbmcgui.Dialog().ok('Scheduled Reminders', list_reminders())
    elif action == 'return_video':
        window.return_to_video()
    elif action == 'search_addons':
        selected_addon = browse_installed_video_addons()
        if selected_addon:
            browse_addon_plugin_folders(selected_addon)
    elif action == 'create_custom_group':
        window.create_custom_group_from_epg()
    elif action == 'manage_custom_groups':
        manage_custom_groups()
    elif action == 'save_playing_stream':
        try:
            _save_playing_stream(channel)
        except Exception as e:
            debug_log(f"DEBUG: Error saving playing stream: {str(e)}", xbmc.LOGERROR)
            xbmcgui.Dialog().notification('Error', f'Failed to save stream: {str(e)}', xbmcgui.NOTIFICATION_ERROR, 3000)
    elif action == 'save_to_kodi_favorites':
        try:
            _save_to_kodi_favorites(channel)
        except Exception as e:
            debug_log(f"DEBUG: Error saving to Kodi favorites: {str(e)}", xbmc.LOGERROR)
            xbmcgui.Dialog().notification('Error', f'Failed to save to Kodi favorites: {str(e)}', xbmcgui.NOTIFICATION_ERROR, 3000)
    elif action == 'pip_start':
        try:
            channel_display = channel.get('name', '') if isinstance(channel, dict) else ''
            from jet_pip import start_pip
            start_pip(channel_display)
            xbmcgui.Dialog().notification('PiP', 'Picture-in-Picture started', xbmcgui.NOTIFICATION_INFO, 3000)
        except Exception as e:
            debug_log(f"DEBUG: Error starting PiP: {str(e)}", xbmc.LOGERROR)
            xbmcgui.Dialog().notification('Error', f'Failed to start PiP: {str(e)}', xbmcgui.NOTIFICATION_ERROR, 3000)
    elif action == 'pip_stop':
        try:
            from jet_pip import stop_pip
            stop_pip()
            xbmcgui.Dialog().notification('PiP', 'Picture-in-Picture stopped', xbmcgui.NOTIFICATION_INFO, 3000)
        except Exception as e:
            debug_log(f"DEBUG: Error stopping PiP: {str(e)}", xbmc.LOGERROR)
            xbmcgui.Dialog().notification('Error', f'Failed to stop PiP: {str(e)}', xbmcgui.NOTIFICATION_ERROR, 3000)
    elif action == 'ai_assistant':
        try:
            from ai_ui import show_ai_dialog
            show_ai_dialog()
        except Exception as e:
            debug_log(f"DEBUG: Error showing AI Assistant: {str(e)}", xbmc.LOGERROR)
            xbmcgui.Dialog().notification('Error', f'AI Assistant error: {str(e)}', xbmcgui.NOTIFICATION_ERROR, 3000)
