# wcs/ai/DialogMyTV.py
import xbmc
import xbmcgui
import xbmcaddon
from urllib.parse import quote_plus
from wcs.ai.DialogAIChatRecommendation import AIChatRecommendationDialog
from wcs.ai.MyTVChannelManager import MyTVChannelManager
from wcs import user_data, utils

class MyTVDialog(AIChatRecommendationDialog):
    def __init__(self, xml_filename, addon_path, *args, **kwargs):
        super(MyTVDialog, self).__init__(xml_filename, addon_path, *args, **kwargs)
        self._nav_section_id = 'my_tv'
        self.channel_manager = MyTVChannelManager(self.addon)
        self.current_channel_index = 0

    def onInit(self):
        self._reset_state()
        self.setProperty('WCS.AIChat.Title', 'Moje televizní vysílání')
        self.setProperty('WCS.AIChat.Status', 'Připraven')
        
        # Always start with the first channel
        self.current_channel_index = 0
        
        # Load View
        self.refresh_channels_view(set_focus=True)
        
        # Ensure sidebar is hidden initially, handled by base class logic or show_nav_sidebar arg
        if self._show_nav_on_init:
            self._show_nav_sidebar(animate=False)
        else:
            self.clearProperty('WCS.AIChat.Visible')

    def refresh_channels_view(self, set_focus=False):
        """Populate the bottom list with channels."""
        channels = self.channel_manager.get_all_channels()
        list_control = self.getControl(2000)
        list_control.reset()
        
        for ch in channels:
            item = xbmcgui.ListItem(label=ch.name)
            # Use channel icon or fallback
            icon = ch.icon if ch.icon else 'special://home/addons/plugin.video.milionar/resources/media/placeholder_tv_card.png'
            item.setArt({'poster': icon})
            item.setProperty('channel_id', ch.id)
            list_control.addItem(item)
            
        # Add "Create New Channel" item
        create_item = xbmcgui.ListItem(label="Vytvořit nový kanál")
        create_item.setArt({'poster': 'special://home/addons/plugin.video.milionar/resources/media/plus_card.png'}) # Fallback to placeholder if not exists
        create_item.setProperty('is_create_button', 'true')
        list_control.addItem(create_item)
            
        # Select first if available (and reset index if out of bounds)
        if self.current_channel_index >= list_control.size():
            self.current_channel_index = 0
            
        if list_control.size() > 0:
            list_control.selectItem(self.current_channel_index)
            self.update_editor_view()
            self.refresh_program_view()
            # Focus on Channel List after 0.5s (only if requested, e.g. on init)
            if set_focus:
                self._delayed_focus(2000, delay=0.5)

    def update_editor_view(self):
        """Update grid 3000 based on selected channel."""
        list_control = self.getControl(2000)
        idx = list_control.getSelectedPosition()
        if idx < 0:
            return
            
        item = list_control.getListItem(idx)
        
        # If "Create New" is selected, clear editor and return
        if item.getProperty('is_create_button') == 'true':
            self.getControl(3000).reset()
            # self.getControl(4000).reset() # Nechame program list byt, at to neblika
            return
            
        channel_id = item.getProperty('channel_id')
        channel = self.channel_manager.get_channel_by_id(channel_id)
        
        grid_control = self.getControl(3000)
        grid_control.reset()
        
        if channel:
            # Add existing series
            for series in channel.series_list:
                s_item = xbmcgui.ListItem(label=series.get('name'))
                poster = series.get('poster_path') or series.get('poster')
                if poster and not poster.startswith('http'):
                     poster = f"https://image.tmdb.org/t/p/w500{poster}"
                elif not poster:
                     poster = 'special://home/addons/plugin.video.milionar/resources/media/placeholder_tv_card.png'
                
                s_item.setArt({'poster': poster})
                s_item.setProperty('series_id', str(series.get('id')))
                s_item.setProperty('channel_id', channel_id)
                grid_control.addItem(s_item)

            # Check if empty - add placeholder "Add First Series" to prevent focus trap
            if grid_control.size() == 0:
                add_item = xbmcgui.ListItem(label="Přidat seriál")
                add_item.setArt({'poster': 'special://home/addons/plugin.video.milionar/resources/media/plus_card.png'})
                add_item.setProperty('is_add_button', 'true')
                add_item.setProperty('channel_id', channel_id)
                grid_control.addItem(add_item)

    def refresh_program_view(self):
        """Generate and display upcoming program with blocks."""
        list_control = self.getControl(2000)
        idx = list_control.getSelectedPosition()
        if idx < 0: return

        item = list_control.getListItem(idx)
        channel_id = item.getProperty('channel_id')
        
        # Store loaded channel ID to avoid stale plays
        self._current_loaded_channel_id = channel_id
        
        channel = self.channel_manager.get_channel_by_id(channel_id)
        
        program_list = self.getControl(4000)
        program_list.reset()
        
        if not channel or not channel.series_list:
             item = xbmcgui.ListItem(label="Žádný program. Přidejte seriály.")
             program_list.addItem(item)
             return

        # Settings for Live TV
        try:
            upcoming_count_val = self.addon.getSetting('mytv_upcoming_count')
            upcoming_count = int(upcoming_count_val) if upcoming_count_val else 12
        except:
            upcoming_count = 12
            
        block_size_setting = self.addon.getSetting('mytv_block_size') # "1", "2", "3", "1-2", "1-3", "2-3"
        if not block_size_setting: block_size_setting = "2"
        
        from wcs.metadata import TMDbClient
        import random
        
        series_candidates = list(channel.series_list)
        random.shuffle(series_candidates) # Randomized channel rotation
        
        # Load history once
        if not hasattr(self, '_recently_played_cache'):
             self._recently_played_cache = user_data.load_recently_played(self.addon)
             
        # Local progress simulation just for this view generation
        simulated_progress = {} # series_id -> (last_season, last_episode)

        generated_count = 0
        candidate_idx = 0
        
        # Limit infinite loop safety
        max_loops = upcoming_count * 2
        loops = 0
        
        while generated_count < upcoming_count and series_candidates and loops < max_loops:
            loops += 1
            # Pick series from rotation
            series = series_candidates[candidate_idx % len(series_candidates)]
            candidate_idx += 1
            
            series_id = str(series.get('id'))
            series_name = series.get('name')
            
            # Initialize progress if needed
            if series_id not in simulated_progress:
                last_season = 1
                last_episode = 0
                for rp in self._recently_played_cache:
                    if str(rp.get('tmdb_id', '')) == series_id and rp.get('media_type') in ['tv', 'episode', 'series']:
                         if 'season' in rp and 'episode' in rp:
                             last_season = int(rp['season'])
                             last_episode = int(rp['episode'])
                         break
                simulated_progress[series_id] = (last_season, last_episode)
            
            # Determine block size
            min_block, max_block = 1, 1
            if '-' in block_size_setting:
                try:
                    parts = block_size_setting.split('-')
                    min_block = int(parts[0])
                    max_block = int(parts[1])
                except: pass
            else:
                try:
                    val = int(block_size_setting)
                    min_block = val
                    max_block = val
                except: pass
            
            current_block_size = random.randint(min_block, max_block)
            
            # Generate block episodes
            for _ in range(current_block_size):
                if generated_count >= upcoming_count: break
                
                curr_s, curr_e = simulated_progress[series_id]
                next_meta = TMDbClient.get_next_episode_from_tmdb(series_id, curr_s, curr_e, self.addon)
                
                if next_meta:
                    # Create List Item - Label je nazev serialu pro novy design
                    ep_name = next_meta.get('episode_title', '')
                    ep_code = f"S{next_meta['season']:02d}E{next_meta['episode']:02d}"
                    
                    # Label = nazev serialu (hlavni), Label2 = runtime
                    item = xbmcgui.ListItem(label=series_name)
                    item.setLabel2(str(next_meta.get('runtime', '')))
                    
                    # Zakladni properties
                    item.setProperty('tmdb_id', series_id)
                    item.setProperty('series_name', series_name)
                    item.setProperty('season', str(next_meta['season']))
                    item.setProperty('episode', str(next_meta['episode']))
                    item.setProperty('episode_title', ep_name)
                    item.setProperty('plot', next_meta.get('plot', ''))
                    item.setProperty('rating', str(next_meta.get('rating', '')))
                    
                    # NOVE properties pro redesign UI
                    item.setProperty('ep_code', ep_code)
                    item.setProperty('series_logo', next_meta.get('series_logo', ''))
                    
                    # Zkraceny plot pro zobrazeni v karte (max 80 znaku)
                    full_plot = next_meta.get('plot', '')
                    if len(full_plot) > 80:
                        plot_short = full_plot[:77] + '...'
                    else:
                        plot_short = full_plot
                    item.setProperty('plot_short', plot_short)
                    
                    # Episode still jako thumb, poster jako icon (fallback)
                    thumb = next_meta.get('episode_thumb') or next_meta.get('poster') or ''
                    icon = next_meta.get('poster') or ''
                    item.setArt({'thumb': thumb, 'icon': icon, 'poster': next_meta.get('poster', ''), 'fanart': next_meta.get('fanart', '')})
                    
                    # Explicitly set properties for retrieval in _play_broadcast
                    item.setProperty('poster', next_meta.get('poster', ''))
                    item.setProperty('fanart', next_meta.get('fanart', ''))
                    item.setProperty('year', str(next_meta.get('year', '')))
                    item.setProperty('genre', next_meta.get('genre', ''))
                    
                    # InfoTag
                    info_tag = {
                        'title': next_meta.get('episode_title', ''),
                        'tvshowtitle': series_name,
                        'plot': next_meta.get('plot', ''),
                        'season': next_meta['season'],
                        'episode': next_meta['episode'],
                        'mediatype': 'episode'
                    }
                    try:
                        dur_min = int(str(next_meta.get('runtime', '0')).replace(' min', ''))
                        info_tag['duration'] = dur_min * 60
                    except: pass
                    
                    utils.set_video_info_tag(item, info_tag)
                    program_list.addItem(item)
                    
                    simulated_progress[series_id] = (next_meta['season'], next_meta['episode'])
                    generated_count += 1
                else:
                    # No more episodes, maybe mark to remove from candidates? for now just break block
                    break

    def onAction(self, action):
        # Detect movement in bottom list to refresh grid
        # ACTION_MOVE_LEFT = 1, ACTION_MOVE_RIGHT = 2
        if self.getFocusId() == 2000:
            if action.getId() in [1, 2]:
                # Allow UI to update selection then refresh
                xbmc.sleep(50)  # Tiny delay to let list update selection
                self.update_editor_view()
                self.refresh_program_view()
        
        super(MyTVDialog, self).onAction(action)

    def onClick(self, controlId):
        if controlId == 2000:
            # Check if "Create New"
            list_control = self.getControl(2000)
            item = list_control.getSelectedItem()
            if item.getProperty('is_create_button') == 'true':
                self._create_new_channel()
            else:
                # Play Channel Broadcast
                # Ensure the program list matches the clicked channel (fix for mouse clicks)
                if getattr(self, '_current_loaded_channel_id', None) != item.getProperty('channel_id'):
                    self.refresh_program_view()
                self._play_broadcast()
        elif controlId == 3000:
            # Context Menu for Grid Item (Remove)
            self._handle_grid_click()
        elif controlId == 3001:
            # Add from My Series
            self._add_from_my_series()
        elif controlId == 3002:
            # Add New (Search)
            self._add_new_search()
        elif controlId == 3003:
            # Delete Channel
            self._delete_current_channel()
        elif controlId == 3004:
            # Play Broadcast (First item in upcoming)
            self._play_broadcast()
        elif controlId == 3005:
            # Refresh/Shuffle
            self.refresh_program_view()
            xbmcgui.Dialog().notification("Moje TV", "Program aktualizován", xbmcgui.NOTIFICATION_INFO)
        elif controlId == 4000:
            # Play Program Item
            self._play_program_item()
        
        super(MyTVDialog, self).onClick(controlId)

    def _create_new_channel(self):
        name = xbmcgui.Dialog().input("Název kanálu", type=xbmcgui.INPUT_ALPHANUM)
        if not name: return
        
        self.channel_manager.create_channel(name)
        # Select the new one (first one)
        self.current_channel_index = 0
        self.current_channel_index = 0
        self.refresh_channels_view(set_focus=False)
        # Auto-trigger "Add from My Series"
        self._add_from_my_series()
        
        # Focus "Start Broadcast" (3004) after dialogs close
        pass

    def _delete_current_channel(self):
        list_control = self.getControl(2000)
        item = list_control.getSelectedItem()
        if not item or item.getProperty('is_create_button') == 'true': return
        
        channel_id = item.getProperty('channel_id')
        channel_name = item.getLabel()
        
        if xbmcgui.Dialog().yesno("Smazat kanál", f"Opravdu chccete smazat kanál '{channel_name}'?"):
            # We need method in manager to delete
            # self.channel_manager.delete_channel(channel_id) # Missing method
            # Let's implement ad-hoc or add to manager. Best to add to manager.
            # For quick fix, I will do it here via accessing list directly, but cleaner is to update manager file.
            # I will update manager file first? No, I can access internal list if I have to, but let's assume I can update manager.
            # Actually I already implemented the manager file in previous turns. I should check if I have delete method.
            # I don't think I added delete method.
            
            # Accessing internal list for now to save tool calls, or re-write manager.
            # Let's rewrite manager slightly or just filter list.
            
            self.channel_manager.channels = [ch for ch in self.channel_manager.channels if ch.id != channel_id]
            self.channel_manager._save_channels()
            
            self.current_channel_index = 0
            self.refresh_channels_view()
            self.current_channel_index = 0
            self.refresh_channels_view()
            self.refresh_channels_view()
            xbmcgui.Dialog().notification("Moje TV", "Kanál smazán.", xbmcgui.NOTIFICATION_INFO)

    def _play_broadcast(self):
        """Plays all items in the upcoming program list continuously."""
        list_control = self.getControl(4000)
        size = list_control.size()
        if size == 0:
            xbmcgui.Dialog().notification("Moje TV", "Žádný program k vysílání.", xbmcgui.NOTIFICATION_INFO)
            return
            
        self.close()
        
        # Get Playlist
        playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
        playlist.clear()
        
        # Add all items to playlist
        for i in range(size):
            item = list_control.getListItem(i)
            
            series_name = item.getProperty('series_name')
            season = item.getProperty('season')
            episode = item.getProperty('episode')
            tmdb_id = item.getProperty('tmdb_id')
            
            if not series_name or not season or not episode:
                continue

            # Metadata params
            episode_title = item.getProperty('episode_title')
            plot = item.getProperty('plot')
            rating = item.getProperty('rating')
            poster = item.getProperty('poster')
            fanart = item.getProperty('fanart')
            genre = item.getProperty('genre')
            year = item.getProperty('year')
            
            # Construct plugin URL for PLAYLIST action
            url = (f"plugin://{self.addon.getAddonInfo('id')}?action=play_episode_from_addon_playlist"
                   f"&series_name={quote_plus(series_name)}"
                   f"&season_number={season}"
                   f"&episode_number={episode}"
                   f"&tmdb_id={tmdb_id}"
                   f"&episode_title={quote_plus(episode_title)}"
                   f"&plot={quote_plus(plot)}"
                   f"&rating={quote_plus(rating)}"
                   f"&poster={quote_plus(poster)}"
                   f"&fanart={quote_plus(fanart)}"
                   f"&genre={quote_plus(genre)}"
                   f"&year={quote_plus(year)}")
            
            # Create list item for playlist
            li = xbmcgui.ListItem(label=item.getLabel())
            li.setInfo('video', {
                'title': item.getLabel(),
                'plot': plot, 
                'year': int(year) if year.isdigit() else 0,
                'premiered': year,
                'mediatype': 'episode',
                'season': int(season),
                'episode': int(episode),
                'tvshowtitle': series_name
            })
            li.setArt({
                'poster': poster,
                'fanart': fanart,
                'thumb': poster
            })
            
            playlist.add(url, li)
            
        # Start playback
        xbmc.Player().play(playlist)

    def _play_program_item(self):
        list_control = self.getControl(4000)
        item = list_control.getSelectedItem()
        if not item: return
        
        series_name = item.getProperty('series_name')
        season = item.getProperty('season')
        episode = item.getProperty('episode')
        tmdb_id = item.getProperty('tmdb_id')
        
        # Metadata pro utils.play_episode_from_addon
        episode_title = item.getProperty('episode_title')
        plot = item.getProperty('plot')
        rating = item.getProperty('rating')
        poster = item.getProperty('poster')
        fanart = item.getProperty('fanart')
        genre = item.getProperty('genre')
        year = item.getProperty('year')
        
        if not series_name or not season or not episode:
             return

        self.close()
        
        # Trigger play action via plugin URL - using standard utils function
        url = (f"plugin://{self.addon.getAddonInfo('id')}?action=play_episode_from_addon"
               f"&series_name={quote_plus(series_name)}"
               f"&season_number={season}"
               f"&episode_number={episode}"
               f"&tmdb_id={tmdb_id}"
               f"&episode_title={quote_plus(episode_title)}"
               f"&plot={quote_plus(plot)}"
               f"&rating={quote_plus(rating)}"
               f"&poster={quote_plus(poster)}"
               f"&fanart={quote_plus(fanart)}"
               f"&genre={quote_plus(genre)}"
               f"&year={quote_plus(year)}")
        
        xbmc.executebuiltin(f"PlayMedia({url})")

    def _play_current_channel(self):
        """Spustí přehrávání aktuálního kanálu (náhodná epizoda Next Up)."""
        list_control = self.getControl(2000)
        item = list_control.getSelectedItem()
        if not item: return
        
        channel_id = item.getProperty('channel_id')
        
        # Najít další epizodu pro přehrání
        next_episode = self.channel_manager.get_random_episode_for_channel(channel_id)
        
        if not next_episode:
            xbmcgui.Dialog().notification(
                self.addon.getAddonInfo('name'),
                "Kanál nemá žádné dostupné epizody",
                xbmcgui.NOTIFICATION_INFO
            )
            return
            
        self.close()
        
        # Přehrát epizodu pomocí standardní akce
        series_name = next_episode.get('series_name') or next_episode.get('series_title')
        season = next_episode.get('season_number')
        episode = next_episode.get('episode_number')
        
        url = (f"plugin://{self.addon.getAddonInfo('id')}?action=play_episode_from_addon"
               f"&series_name={quote_plus(series_name)}"
               f"&season_number={season}"
               f"&episode_number={episode}"
               f"&tmdb_id={next_episode.get('tmdb_id', '')}"
               f"&episode_title={quote_plus(next_episode.get('episode_title', ''))}"
               f"&plot={quote_plus(next_episode.get('episode_plot', ''))}"
               f"&rating={quote_plus(str(next_episode.get('episode_rating', '')))}"
               f"&poster={quote_plus(next_episode.get('series_poster', ''))}"
               f"&fanart={quote_plus(next_episode.get('series_fanart', ''))}"
               f"&year={quote_plus(str(next_episode.get('episode_year', '')))}")
        
        xbmc.executebuiltin(f"PlayMedia({url})")


    def _handle_grid_click(self):
        grid = self.getControl(3000)
        item = grid.getSelectedItem()
        if not item: return
        
        # Check if it's the "Add Series" placeholder
        if item.getProperty('is_add_button') == 'true':
            self._add_from_my_series()
            return

        series_label = item.getLabel()
        channel_id = item.getProperty('channel_id')
        series_id = item.getProperty('series_id')
        
        # Context menu
        menu = xbmcgui.Dialog().contextmenu([f"Smazat '{series_label}' z kanálu"])
        if menu == 0:
            # Remove
            self.channel_manager.toggle_series_in_channel(channel_id, {'id': series_id})
            # Refresh editor view only to keep focus position best as possible
            self.update_editor_view()
            self.refresh_program_view()
            self.setFocusId(3000) # Keep focus in grid
            xbmcgui.Dialog().notification("Moje TV", f"'{series_label}' odebráno.", xbmcgui.NOTIFICATION_INFO)

    def _add_from_my_series(self):
        # Get My Series
        my_series = user_data.load_tmdb_series(self.addon)
        if not my_series:
             xbmcgui.Dialog().notification("Moje TV", "Nenalezeny žádné uložené seriály.", xbmcgui.NOTIFICATION_INFO)
             return
             
        # Filter out already added ones?
        list_control = self.getControl(2000)
        channel_id = list_control.getSelectedItem().getProperty('channel_id')
        channel = self.channel_manager.get_channel_by_id(channel_id)
        current_ids = [str(s.get('id')) for s in channel.series_list]
        
        candidates = [s for s in my_series if str(s.get('id')) not in current_ids]
        
        if not candidates:
             xbmcgui.Dialog().notification("Moje TV", "Všechny vaše seriály už jsou v kanálu.", xbmcgui.NOTIFICATION_INFO)
             return
             
        # Multi select
        labels = [f"{s.get('name')} ({s.get('year', '')})" for s in candidates]
        selected = xbmcgui.Dialog().multiselect("Přidat do kanálu", labels)
        
        if selected:
            for idx in selected:
                self.channel_manager.toggle_series_in_channel(channel_id, candidates[idx])
            # Refresh editor view
            self.update_editor_view()
            self.refresh_program_view()
            self.setFocusId(3000)
            xbmcgui.Dialog().notification("Moje TV", "Seriály přidány.", xbmcgui.NOTIFICATION_INFO)

    def _add_new_search(self):
        # Copied logic from DialogMySeries, adapted
        import requests
        from wcs.metadata.TMDbClient import get_tmdb_api_key
        
        search_query = xbmcgui.Dialog().input("Hledat seriál", type=xbmcgui.INPUT_ALPHANUM)
        if not search_query: return
        
        try:
            url = f'https://api.themoviedb.org/3/search/tv?api_key={get_tmdb_api_key()}&language=cs-CZ&query={quote_plus(search_query)}'
            response = requests.get(url, timeout=10)
            results = response.json().get('results', [])
        except Exception:
            return
            
        if not results:
             xbmcgui.Dialog().notification("Moje TV", "Nic nenalezeno.", xbmcgui.NOTIFICATION_INFO)
             return
             
        choices = [f"{item['name']} ({item.get('first_air_date', '')[:4]})" for item in results]
        selected_idx = xbmcgui.Dialog().select("Vyberte seriál", choices)
        
        if selected_idx >= 0:
            selected_item = results[selected_idx]
            list_control = self.getControl(2000)
            channel_id = list_control.getSelectedItem().getProperty('channel_id')
            
            self.channel_manager.toggle_series_in_channel(channel_id, selected_item)
            self.channel_manager.toggle_series_in_channel(channel_id, selected_item)
            # Full refresh
            self.update_editor_view()
            self.refresh_program_view()
            self.setFocusId(3000)
            xbmcgui.Dialog().notification("Moje TV", f"'{selected_item['name']}' přidáno.", xbmcgui.NOTIFICATION_INFO)


def show_my_tv_dialog(addon, show_nav_sidebar=False, nav_position=0):
    dialog = MyTVDialog(
        "ai/DialogMyTV.xml",
        addon.getAddonInfo('path'),
        "Default",
        "1080i",
        show_nav_sidebar=show_nav_sidebar,
        nav_position=nav_position
    )
    dialog.doModal()
    del dialog
