"""
UI components and styling for the auto clicker application.
"""

import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
from .constants import (
    FONT, HEADER_FONT, SIDEBAR_FONT,
    MINIMIZED_WIDTH, MINIMIZED_HEIGHT, FULL_WIDTH, FULL_HEIGHT, FULL_HEIGHT_WITH_DEBUG,
    BACKGROUND_COLOR, CARD_BACKGROUND, MINIMIZED_BACKGROUND, BORDER_COLOR,
    TEXT_COLOR, PRIMARY_COLOR, RECORDING_COLOR, PLAY_COLOR, STOP_COLOR,
    SUPPORTED_SUBPLAYLIST_APP_IDS
)
from .utils import calculate_screen_position


class UIManager:
    """Manages UI creation and styling for the main application."""
    
    def __init__(self, app):
        self.app = app
        # Track Play buttons for dynamic enable/disable
        self._play_buttons = []
        # Listen for status changes to update Play button state
        try:
            var = getattr(self.app, 'status_var', None)
            if var is not None:
                if hasattr(var, 'trace_add'):
                    var.trace_add('write', self._on_status_change)
                else:
                    var.trace('w', self._on_status_change)
        except Exception:
            pass
        
    def create_widgets(self):
        """Create widgets based on current view state."""
        # Reset tracked buttons before rebuilding
        try:
            self._play_buttons = []
        except Exception:
            pass
        if self.app._main_frame:
            self.app._main_frame.destroy()
        if self.app._min_frame:
            self.app._min_frame.destroy()
            
        if self.app.is_minimized:
            self.create_minimized_view()
        else:
            self.create_full_view()

    def create_minimized_view(self):
        """Create the minimized view with vertical button layout."""
        screen_width = self.app.winfo_screenwidth()
        screen_height = self.app.winfo_screenheight()
        width = MINIMIZED_WIDTH if MINIMIZED_WIDTH > 0 else 100
        height = MINIMIZED_HEIGHT if MINIMIZED_HEIGHT > 0 else 200
        width = min(width, max(200, screen_width))
        height = min(height, max(150, screen_height))
        min_y = calculate_screen_position(screen_height, height)
        self.app.geometry(f'{width}x{height}+0+{min_y}')
        
        self.app._min_frame = tk.Frame(self.app, bg=MINIMIZED_BACKGROUND)
        self.app._min_frame.pack(fill='both', expand=True)
        
        # Blue indicator if playing
        if self.app.status_var.get() == 'Playing':
            indicator = tk.Frame(self.app._min_frame, bg=PLAY_COLOR, height=6)
            indicator.pack(fill='x', side='top')
        
        # Logo
        self._create_logo(self.app._min_frame, size=28, bg=MINIMIZED_BACKGROUND)
        
        # Button frame
        btn_frame = tk.Frame(self.app._min_frame, bg=MINIMIZED_BACKGROUND)
        btn_frame.pack(fill='both', expand=True)
        
        # Create buttons
        self._create_minimized_buttons(btn_frame)

        # After widgets are laid out, resize height to fit content (clamped to screen)
        try:
            self.app.update_idletasks()
            req_h = max(self.app._min_frame.winfo_reqheight(), self.app._min_frame.winfo_height() or 0)
            # Keep the width as chosen, adjust height only
            final_h = min(max(req_h, MINIMIZED_HEIGHT), screen_height - 10)
            final_y = calculate_screen_position(screen_height, final_h)
            self.app.geometry(f'{width}x{final_h}+0+{final_y}')
        except Exception:
            pass

    def create_full_view(self):
        """Create the full view with all controls."""
        # Auto-scale height if debug view is open
        if self.app.debug_window and self.app.debug_window.winfo_exists():
            full_height = FULL_HEIGHT_WITH_DEBUG
        else:
            full_height = FULL_HEIGHT
            
        screen_width = self.app.winfo_screenwidth()
        screen_height = self.app.winfo_screenheight()
        full_width = FULL_WIDTH if FULL_WIDTH > 0 else 700
        full_width = min(full_width, screen_width)
        full_height = min(full_height, screen_height)
        full_y = calculate_screen_position(screen_height, full_height)
        self.app.geometry(f'{full_width}x{full_height}+0+{full_y}')
        
        self.app._main_frame = tk.Frame(self.app, bg=BACKGROUND_COLOR)
        self.app._main_frame.pack(fill='both', expand=True)
        
        # Logo at top left
        self._create_logo(self.app._main_frame, size=40, bg=BACKGROUND_COLOR, position=(10, 10))
        
        # If no playlist is selected/available (and not in user interaction mode),
        # show only a single informational message and the minimize/maximize button.
        no_playlist = False
        if not getattr(self.app, 'user_interaction_mode', False):
            try:
                playlist_value = ''
                if getattr(self.app, 'selected_playlist', None):
                    try:
                        playlist_value = (self.app.selected_playlist.get() or '').strip()
                    except Exception:
                        playlist_value = ''
                no_playlist = playlist_value in ('', 'Select playlist', 'No playlists found')
            except Exception:
                no_playlist = False

        if no_playlist:
            card = tk.Frame(
                self.app._main_frame,
                bg=CARD_BACKGROUND,
                bd=0,
                highlightthickness=1,
                highlightbackground=BORDER_COLOR
            )
            card.pack(padx=30, pady=10, fill='x')
            tk.Label(
                card,
                text='Please wait while fetching a playlist…',
                font=FONT,
                bg=CARD_BACKGROUND,
                fg=TEXT_COLOR,
                wraplength=FULL_WIDTH - 60,
                justify='left',
                anchor='w'
            ).pack(anchor='w', padx=10, pady=(10, 10))
            # Keep minimize/maximize button available
            row_frame = tk.Frame(card, bg=CARD_BACKGROUND)
            row_frame.pack(fill='x', padx=10, pady=(0, 6))
            try:
                from tkinter import ttk as _ttk
                minimize_btn = _ttk.Button(row_frame, text='⤢', command=self.app.toggle_view, style='Dark.TButton')
            except Exception:
                minimize_btn = ttk.Button(row_frame, text='⤢', command=self.app.toggle_view, style='Dark.TButton')
            minimize_btn.pack(side='right', padx=6, pady=2)
            try:
                self.app.add_tooltip(minimize_btn, 'Minimize/Maximize')
            except Exception:
                pass
            # Skip fields, buttons, and live clicks in this state
            self._apply_styles()
            return

        # Main card
        self._create_main_card()
        
        # Live clicks view
        self._create_live_clicks_view()
        
        # Apply styles
        self._apply_styles()

    def _create_logo(self, parent, size, bg, position=None):
        """Create and place the logo."""
        try:
            logo_img = Image.open('audit_whizz_logo_transparent.png').resize((size, size), Image.ANTIALIAS)
            if size == 28:
                self.app.logo_photo = ImageTk.PhotoImage(logo_img)
            else:
                self.app.logo_photo_full = ImageTk.PhotoImage(logo_img)
                
            logo_label = tk.Label(
                parent, 
                image=self.app.logo_photo if size == 28 else self.app.logo_photo_full, 
                bg=bg
            )
            
            if position:
                logo_label.place(x=position[0], y=position[1])
            else:
                logo_label.pack(pady=(10, 8))
        except Exception as e:
            if size == 28:
                self.app.logo_photo = None
            else:
                self.app.logo_photo_full = None

    def _create_minimized_buttons(self, parent):
        """Create buttons for minimized view."""
        # If no playlist is available/selected, show a helpful message and no buttons
        try:
            playlist_value = ''
            if getattr(self.app, 'selected_playlist', None):
                try:
                    playlist_value = (self.app.selected_playlist.get() or '').strip()
                except Exception:
                    playlist_value = ''
            no_playlist = playlist_value in ('', 'Select playlist', 'No playlists found')
        except Exception:
            no_playlist = False

        if no_playlist and not getattr(self.app, 'user_interaction_mode', False):
            lbl = tk.Label(
                parent,
                text='Please wait while fetching a playlist…',
                font=('Segoe UI', 9),
                bg=MINIMIZED_BACKGROUND,
                fg='#6c757d',
                wraplength=MINIMIZED_WIDTH - 16,
                justify='center'
            )
            lbl.pack(pady=6, padx=8, fill='x')
            return

        if getattr(self.app, 'user_interaction_mode', False):
            # In user interaction mode, show Done, Cancel, and Minimize/Maximize buttons
            buttons = [
                ('✓', self.app.on_user_interaction_done, PRIMARY_COLOR, 'Done - Click when user interaction is complete'),
                ('✖', self.app.on_cancel_playlist, STOP_COLOR, 'Cancel Playlist'),
                ('⤡', self.app.toggle_view, STOP_COLOR, 'Minimize/Maximize'),
            ]
        else:
            # Conditional minimized view based on mode/role
            try:
                mode = (getattr(self.app, 'current_playlist_mode', None) or '').strip().lower()
            except Exception:
                mode = ''
            role = getattr(self.app, 'ui_role', 'user')

            # In 'new' mode, hide Play even for admin
            if mode == 'new':
                # User (new playlist): only essential buttons
                buttons = [
                    ('⏺', self.app.on_start_recording, RECORDING_COLOR, 'Start Recording'),
                    ('⏹', self.app.on_stop_recording, STOP_COLOR, 'Stop Recording/Playback'),
                    ('💾', self.app.on_save_playlist, PLAY_COLOR, 'Save Playlist'),
                    ('IV', self.app.on_input_variable, PLAY_COLOR, 'Add Input Variable'),
                    ('🔎', self.app.on_search_input, PLAY_COLOR, 'Search on screen and type value'),
                    ('📸', self.app.on_manual_screenshot, STOP_COLOR, 'Manual Screenshot'),
                    ('✖', self.app.on_cancel_playlist, STOP_COLOR, 'Cancel Playlist'),
                    ('⤡', self.app.toggle_view, STOP_COLOR, 'Maximize'),
                ]
            elif role == 'admin':
                # Admin minimized view (non-new mode)
                buttons = [
                    ('⏺', self.app.on_start_recording, RECORDING_COLOR, 'Start Recording'),
                    ('▶', self.app.on_play_playlist, PLAY_COLOR, 'Play Playlist'),
                    ('⏹', self.app.on_stop_recording, STOP_COLOR, 'Stop Recording/Playback'),
                    ('✖', self.app.on_cancel_playlist, STOP_COLOR, 'Cancel Playlist'),
                    ('📸', self.app.on_manual_screenshot, STOP_COLOR, 'Manual Screenshot'),
                    ('⤡', self.app.toggle_view, STOP_COLOR, 'Maximize'),
                ]
            else:
                # Default minimized when not in 'new' mode
                buttons = [
                    # ('⏺', self.app.on_start_recording, RECORDING_COLOR, 'Start Recording'),
                    ('▶', self.app.on_play_playlist, PLAY_COLOR, 'Play Playlist'),
                    ('⏹', self.app.on_stop_recording, STOP_COLOR, 'Stop Recording/Playback'),
                    ('✖', self.app.on_cancel_playlist, STOP_COLOR, 'Cancel Playlist'),
                    # ('📸', self.app.on_manual_screenshot, STOP_COLOR, 'Manual Screenshot'),
                    ('⤡', self.app.toggle_view, STOP_COLOR, 'Maximize'),
                ]
        
        for text, command, color, tooltip in buttons:
            btn = tk.Button(
                parent,
                text=text,
                font=('Segoe UI', 12),
                fg=color,
                bg='#fff',
                relief='flat',
                command=command,
                width=2,
                height=1
            )
            btn.pack(pady=2, fill='x')
            self.app.add_tooltip(btn, tooltip)
            # Track Play button for dynamic updates
            if text == '▶':
                try:
                    self._play_buttons.append(btn)
                except Exception:
                    pass
            # In 'new' mode before recording starts, only allow Record, Cancel, and Minimize/Maximize
            try:
                mode = (getattr(self.app, 'current_playlist_mode', None) or '').strip().lower()
            except Exception:
                mode = ''
            if mode == 'new' and not getattr(self.app, 'recording', False):
                allowed = {'⏺', '✖', '⤡', '✓'}
                allow_save_now = (text == '💾' and self._has_actions_to_save())
                if text not in allowed and not allow_save_now:
                    try:
                        btn.configure(state='disabled')
                    except Exception:
                        pass
            # While recording a new playlist, disable the Record button to prevent duplicate starts
            try:
                mode = (getattr(self.app, 'current_playlist_mode', None) or '').strip().lower()
            except Exception:
                mode = ''
            if mode == 'new' and getattr(self.app, 'recording', False) and text == '⏺':
                try:
                    btn.configure(state='disabled')
                except Exception:
                    pass
            # While recording, ensure Save is enabled explicitly
            if getattr(self.app, 'recording', False) and text == '💾':
                try:
                    btn.configure(state='normal')
                except Exception:
                    pass
            # Disable Play button while playback is active (independent of status text)
            try:
                is_playing = bool(getattr(self.app, 'is_playback_active', False))
            except Exception:
                is_playing = False
            if is_playing and text == '▶':
                try:
                    btn.configure(state='disabled')
                except Exception:
                    pass

    def _create_main_card(self):
        """Create the main card with controls."""
        card = tk.Frame(
            self.app._main_frame,
            bg=CARD_BACKGROUND,
            bd=0,
            highlightthickness=1,
            highlightbackground=BORDER_COLOR
        )
        card.pack(padx=30, pady=10, fill='x')
        card.grid_columnconfigure(0, weight=1)
        card.grid_columnconfigure(1, weight=1)
        card.grid_columnconfigure(2, weight=1)
        
        # Fields frame
        self._create_fields_frame(card)
        
        # Action buttons
        self._create_action_buttons(card)
        
        # Status label (reuse existing variable; do not reset state)
        if not getattr(self.app, 'status_var', None):
            self.app.status_var = tk.StringVar(value='Idle')
            try:
                var = self.app.status_var
                if hasattr(var, 'trace_add'):
                    var.trace_add('write', self._on_status_change)
                else:
                    var.trace('w', self._on_status_change)
            except Exception:
                pass
        tk.Label(
            card,
            textvariable=self.app.status_var,
            font=FONT,
            bg=CARD_BACKGROUND,
            fg=PRIMARY_COLOR
        ).pack(anchor='e', padx=10)

    def _create_fields_frame(self, parent):
        """Create the input fields frame."""
        fields_frame = tk.Frame(parent, bg=CARD_BACKGROUND)
        fields_frame.pack(fill='x', padx=10, pady=(10, 0))
        
        # Application label (read-only display when auto-selected)
        tk.Label(
            fields_frame,
            text='Application:',
            font=FONT,
            bg=CARD_BACKGROUND,
            fg=TEXT_COLOR
        ).pack(side='left', padx=(0, 4))

        # Get application name from current_application_name if available
        app_name = getattr(self.app, 'current_application_name', 'No application selected')
        self.app.selected_application.set(app_name)
        
        tk.Label(
            fields_frame,
            textvariable=self.app.selected_application,
            font=FONT,
            bg=CARD_BACKGROUND,
            fg=PRIMARY_COLOR,
            width=18,
            anchor='w'
        ).pack(side='left', padx=(0, 12))

        # Recording name display (non-editable). Always show the playlist/recording
        # name as a read-only label bound to `selected_playlist`. The underlying
        # `recording_name_var` is still kept for direct-integration flows and
        # saving, but the user cannot edit it inline.
        if not getattr(self.app, 'hide_recording_name', False):
            tk.Label(
                fields_frame,
                text='Playlist Name:',
                font=FONT,
                bg=CARD_BACKGROUND,
                fg=TEXT_COLOR
            ).pack(side='left')

            # Ensure the variables exist and stay in sync
            if getattr(self.app, 'selected_playlist', None) is None:
                self.app.selected_playlist = tk.StringVar()
            try:
                if getattr(self.app, 'recording_name_var', None):
                    # Keep selected label and recording_name aligned for saving/recording
                    name_now = (self.app.selected_playlist.get() or '').strip()
                    if not name_now:
                        self.app.selected_playlist.set((self.app.recording_name_var.get() or '').strip())
            except Exception:
                pass

            tk.Label(
                fields_frame,
                textvariable=self.app.selected_playlist,
                font=FONT,
                bg=CARD_BACKGROUND,
                fg=PRIMARY_COLOR,
                width=20,
                anchor='w'
            ).pack(side='left', padx=5)

        # Admin-effective checkbox for Sub playlist: when checked, mark show_on=0 on save
        # Visible when either explicitly in admin view, or during admin upload creating a new playlist
        try:
            mode = (getattr(self.app, 'current_playlist_mode', None) or '').strip().lower()
        except Exception:
            mode = ''
        role = getattr(self.app, 'ui_role', 'user')
        try:
            is_admin_upload = bool(getattr(self.app, 'current_is_admin', False))
        except Exception:
            is_admin_upload = False
        admin_effective = (role == 'admin') or (is_admin_upload and mode == 'new')
        if admin_effective:
            # Spacer
            tk.Label(
                fields_frame,
                text=' ',
                font=FONT,
                bg=CARD_BACKGROUND,
                fg=TEXT_COLOR
            ).pack(side='left', padx=(10, 0))

            chk = ttk.Checkbutton(
                fields_frame,
                text='Sub playlist',
                variable=self.app.hide_on_subplaylist_var,
                style='TCheckbutton'
            )
            chk.pack(side='left', padx=(0, 6))
            try:
                self.app.add_tooltip(chk, 'If checked: hide this playlist from list (show_on=0)')
            except Exception:
                pass
        
        # # Playlist display: show read-only label when `playlists` list is empty; otherwise show dropdown
        # tk.Label(
        #     fields_frame,
        #     text='Playlist:',
        #     font=FONT,
        #     bg=CARD_BACKGROUND,
        #     fg=TEXT_COLOR
        # ).pack(side='left', padx=(20, 0))

        # if getattr(self.app, 'playlists', None) and len(self.app.playlists) > 0:
        #     self.app.playlist_dropdown = ttk.Combobox(
        #         fields_frame,
        #         textvariable=self.app.selected_playlist,
        #         values=self.app.playlists,
        #         state='readonly',
        #         width=18,
        #         font=FONT
        #     )
        #     self.app.playlist_dropdown.pack(side='left', padx=5)
        #     self.app.playlist_dropdown.set('Select playlist')
        #     self.app.playlist_dropdown.bind('<<ComboboxSelected>>', self.app.on_playlist_selected)
        # else:
        #     # Read-only label showing chosen playlist (new or existing) without dropdown
        #     tk.Label(
        #         fields_frame,
        #         textvariable=self.app.selected_playlist,
        #         font=FONT,
        #         bg=CARD_BACKGROUND,
        #         fg=PRIMARY_COLOR,
        #         width=18,
        #         anchor='w'
        #     ).pack(side='left', padx=5)
        
        # # Wait time
        # tk.Label(
        #     fields_frame,
        #     text='Wait (s):',
        #     font=FONT,
        #     bg=CARD_BACKGROUND,
        #     fg=TEXT_COLOR
        # ).pack(side='left', padx=(20, 0))
        
        # self.app.wait_time_var = tk.StringVar(value='0')
        # self.app.wait_time_entry = ttk.Entry(
        #     fields_frame,
        #     textvariable=self.app.wait_time_var,
        #     width=5,
        #     font=FONT
        # )
        # self.app.wait_time_entry.pack(side='left', padx=5)

    def _create_action_buttons(self, parent):
        """Create action buttons in rows."""
        # If the app is waiting for user interaction (login/site), replace the
        # regular action buttons with a single "Done" button. Otherwise show
        # the normal set of action buttons.
        if getattr(self.app, 'user_interaction_mode', False):
            row_frame = tk.Frame(parent, bg=CARD_BACKGROUND)
            row_frame.pack(fill='x', padx=10, pady=(5, 0))
            
            # Done button
            done_btn = ttk.Button(row_frame, text='Done', command=self.app.on_user_interaction_done, style='Dark.TButton')
            done_btn.pack(side='left', padx=6, pady=2)
            self.app.add_tooltip(done_btn, 'Click when you have completed the required user interaction')
            
            # Cancel button
            cancel_btn = ttk.Button(row_frame, text='Cancel', command=self.app.on_cancel_playlist, style='Red.TButton')
            cancel_btn.pack(side='left', padx=6, pady=2)
            self.app.add_tooltip(cancel_btn, 'Cancel current playlist and reset')

            # Admin View toggle button (only if is_admin = 1 on the upload)
            try:
                if bool(getattr(self.app, 'current_is_admin', False)):
                    role = getattr(self.app, 'ui_role', 'user')
                    label = 'Admin View' if role != 'admin' else 'User View'
                    admin_btn = ttk.Button(row_frame, text=label, command=self.app.toggle_admin_view, style='Dark.TButton')
                    admin_btn.pack(side='left', padx=6, pady=2)
                    self.app.add_tooltip(admin_btn, 'Toggle Admin/User view')
            except Exception:
                pass

            # Add minimize/maximize button
            minimize_btn = ttk.Button(row_frame, text='⤢', command=self.app.toggle_view, style='Dark.TButton')
            minimize_btn.pack(side='right', padx=6, pady=2)
            self.app.add_tooltip(minimize_btn, 'Minimize/Maximize')

            # If admin view is active, render full admin controls below the interaction row
            try:
                if bool(getattr(self.app, 'current_is_admin', False)) and getattr(self.app, 'ui_role', 'user') == 'admin':
                    # Build admin controls similar to full view
                    admin_buttons = [
                        ('Record', self.app.on_start_recording, 'Dark.TButton', 'Record'),
                        ('Play', self.app.on_play_playlist, 'Dark.TButton', 'Play'),
                        ('Stop', self.app.on_stop_recording, 'Dark.TButton', 'Stop'),
                        ('Save', self.app.on_save_playlist, 'Dark.TButton', 'Save Playlist'),
                        ('Input Variable', self.app.on_input_variable, 'Dark.TButton', 'Add Input Variable'),
                        ('Search', self.app.on_search_input, 'Dark.TButton', 'Search for UI element by value using OpenAI'),
                        ('Screenshot', self.app.on_manual_screenshot, 'Dark.TButton', 'Screenshot'),
                        ('Get Support Docs', self.app.on_get_supporting_documents, 'Dark.TButton', 'Get Supporting Documents (routes by app)'),
                        ('Analyze Docs', self.app.on_analyze_supporting_documents, 'Dark.TButton', 'Analyze Current Screen for Supporting Documents'),
                        ('SD', self.app.on_analyze_sd_icons, 'Dark.TButton', 'Analyze Current Screen for SD (Supporting Document) Icons'),
                        ('Add Subplaylist', self.app.on_add_subplaylist_action, 'Dark.TButton', 'Add a subplaylist action to current recording'),
                        # ('Export', self.app.on_export_json, 'Dark.TButton', 'Export Playlist'),  # Hidden per requirements
                        ('Delete', self.app.on_delete_playlist_mysql, 'Red.TButton', 'Delete Playlist from Both Databases'),
                        # ('Check Queue', self.app.check_auto_extractor_queue_once, 'Dark.TButton', 'Check Auto Extractor Queue'),  # Hidden per requirements
                    ]
                    # Render in rows of 4
                    btn_rows = []
                    for i in range(0, len(admin_buttons), 4):
                        btn_rows.append(admin_buttons[i:i+4])
                    for row in btn_rows:
                        a_row = tk.Frame(parent, bg=CARD_BACKGROUND)
                        a_row.pack(fill='x', padx=10, pady=(5, 0))
                        for text, cmd, style, tooltip in row:
                            btn = ttk.Button(a_row, text=text, command=cmd, style=style)
                            btn.pack(side='left', padx=6, pady=2)
                            self.app.add_tooltip(btn, tooltip)
            except Exception:
                pass

            return

        # Hide buttons entirely if no playlist is selected/available, show message instead
        try:
            playlist_value = ''
            if getattr(self.app, 'selected_playlist', None):
                try:
                    playlist_value = (self.app.selected_playlist.get() or '').strip()
                except Exception:
                    playlist_value = ''
            no_playlist = playlist_value in ('', 'Select playlist', 'No playlists found')
        except Exception:
            no_playlist = False

        if no_playlist:
            row_frame = tk.Frame(parent, bg=CARD_BACKGROUND)
            row_frame.pack(fill='x', padx=10, pady=(5, 6))
            tk.Label(
                row_frame,
                text='Please wait while fetching a playlist…',
                font=FONT,
                bg=CARD_BACKGROUND,
                fg='#6c757d',
                wraplength=FULL_WIDTH - 60,
                justify='left',
                anchor='w'
            ).pack(side='left', padx=6, pady=2, fill='x')
            return

        # Build button configuration based on mode/role
        try:
            mode = (getattr(self.app, 'current_playlist_mode', None) or '').strip().lower()
        except Exception:
            mode = ''
        role = getattr(self.app, 'ui_role', 'user')
        # Effective admin: either explicitly in admin view, or admin upload creating a new playlist
        try:
            is_admin_upload = bool(getattr(self.app, 'current_is_admin', False))
        except Exception:
            is_admin_upload = False
        admin_effective = (role == 'admin') or (is_admin_upload and mode == 'new')

        # In 'new' mode, hide Play even for admin
        if mode == 'new':
            # User view for new playlist: exact requested set (no Play/Export/Delete/etc.)
            base_buttons = [
                ('Record', self.app.on_start_recording, 'Dark.TButton', 'Record'),
                ('Stop', self.app.on_stop_recording, 'Dark.TButton', 'Stop'),
                ('Save', self.app.on_save_playlist, 'Dark.TButton', 'Save Playlist'),
                ('Input Variable', self.app.on_input_variable, 'Dark.TButton', 'Add Input Variable'),
                ('Search', self.app.on_search_input, 'Dark.TButton', 'Search for UI element by value using OpenAI'),
                ('Screenshot', self.app.on_manual_screenshot, 'Dark.TButton', 'Screenshot'),
                ('Get Support Docs', self.app.on_get_supporting_documents, 'Dark.TButton', 'Get Supporting Documents (routes by app)'),
                ('Analyze Docs', self.app.on_analyze_supporting_documents, 'Dark.TButton', 'Analyze Current Screen for Supporting Documents'),
                ('Cancel', self.app.on_cancel_playlist, 'Red.TButton', 'Cancel current playlist and reset'),
                ('⤢', self.app.toggle_view, 'Dark.TButton', 'Minimize/Maximize'),
            ]
        elif admin_effective:
            base_buttons = [
                ('Record', self.app.on_start_recording, 'Dark.TButton', 'Record'),
                ('Play', self.app.on_play_playlist, 'Dark.TButton', 'Play'),
                ('Stop', self.app.on_stop_recording, 'Dark.TButton', 'Stop'),
                ('Save', self.app.on_save_playlist, 'Dark.TButton', 'Save Playlist'),
                ('Input Variable', self.app.on_input_variable, 'Dark.TButton', 'Add Input Variable'),
                ('Search', self.app.on_search_input, 'Dark.TButton', 'Search for UI element by value using OpenAI'),
                ('Screenshot', self.app.on_manual_screenshot, 'Dark.TButton', 'Screenshot'),
                ('Get Support Docs', self.app.on_get_supporting_documents, 'Dark.TButton', 'Get Supporting Documents (routes by app)'),
                ('Analyze Docs', self.app.on_analyze_supporting_documents, 'Dark.TButton', 'Analyze Current Screen for Supporting Documents'),
                # ('SD', self.app.on_analyze_sd_icons, 'Dark.TButton', 'Analyze Current Screen for SD (Supporting Document) Icons'),
                ('Add Subplaylist', self.app.on_add_subplaylist_action, 'Dark.TButton', 'Add a subplaylist action to current recording'),
                # ('Export', self.app.on_export_json, 'Dark.TButton', 'Export Playlist'),  # Hidden per requirements
                ('Delete', self.app.on_delete_playlist_mysql, 'Red.TButton', 'Delete Playlist from Both Databases'),
                ('Cancel', self.app.on_cancel_playlist, 'Red.TButton', 'Cancel current playlist and reset'),
                # ('Check Queue', self.app.check_auto_extractor_queue_once, 'Dark.TButton', 'Check Auto Extractor Queue'),  # Hidden per requirements
                ('⤢', self.app.toggle_view, 'Dark.TButton', 'Minimize/Maximize'),
            ]
        else:
            # Default/full user view for existing playlists
            base_buttons = [
                # ('Record', self.app.on_start_recording, 'Dark.TButton', 'Record'),
                ('Play', self.app.on_play_playlist, 'Dark.TButton', 'Play'),
                ('Stop', self.app.on_stop_recording, 'Dark.TButton', 'Stop'),
                # ('Save', self.app.on_save_playlist, 'Dark.TButton', 'Save Playlist'),
                # ('Input Variable', self.app.on_input_variable, 'Dark.TButton', 'Add Input Variable'),
                # ('Search', self.app.on_search_input, 'Dark.TButton', 'Search for UI element by value using OpenAI'),
                # ('Screenshot', self.app.on_manual_screenshot, 'Dark.TButton', 'Screenshot'),
                # ('Get Support Docs', self.app.on_get_supporting_documents, 'Dark.TButton', 'Get Supporting Documents (routes by app)'),
                # ('Analyze Docs', self.app.on_analyze_supporting_documents, 'Dark.TButton', 'Analyze Current Screen for Supporting Documents'),
                ('Cancel', self.app.on_cancel_playlist, 'Red.TButton', 'Cancel current playlist and reset'),
                ('⤢', self.app.toggle_view, 'Dark.TButton', 'Minimize/Maximize'),
            ]

        # No subplaylist placeholder; single Support Docs button routes internally by app_id
        
        # Continue button no longer required; value dialog drives flow
                
        btn_configs = base_buttons
        
        # Split into rows of 4
        btn_rows = []
        for i in range(0, len(btn_configs), 4):
            btn_rows.append(btn_configs[i:i+4])
            
        for row in btn_rows:
            row_frame = tk.Frame(parent, bg=CARD_BACKGROUND)
            row_frame.pack(fill='x', padx=10, pady=(5, 0))
            
            for text, cmd, style, tooltip in row:
                btn = ttk.Button(row_frame, text=text, command=cmd, style=style)
                btn.pack(side='left', padx=6, pady=2)
                self.app.add_tooltip(btn, tooltip)
                # Track Play button for dynamic updates
                if text == 'Play':
                    try:
                        self._play_buttons.append(btn)
                    except Exception:
                        pass
                # In 'new' mode before recording starts, only allow Record, Cancel, and Minimize/Maximize
                # but allow Save if there are recorded actions available
                if mode == 'new' and not getattr(self.app, 'recording', False):
                    allowed = {'Record', 'Cancel', '⤢'}
                    allow_save_now = (text == 'Save' and self._has_actions_to_save())
                    if text not in allowed and not allow_save_now:
                        try:
                            btn.state(['disabled'])
                        except Exception:
                            try:
                                btn.configure(state='disabled')
                            except Exception:
                                pass
                # While recording a new playlist, disable the Record button to prevent duplicate starts
                if mode == 'new' and getattr(self.app, 'recording', False) and text == 'Record':
                    try:
                        btn.state(['disabled'])
                    except Exception:
                        try:
                            btn.configure(state='disabled')
                        except Exception:
                            pass
                # While recording, ensure Save is enabled explicitly
                if getattr(self.app, 'recording', False) and text == 'Save':
                    try:
                        btn.state(['!disabled'])
                    except Exception:
                        try:
                            btn.configure(state='normal')
                        except Exception:
                            pass
                # Disable Play button while playback is active (independent of status text)
                try:
                    is_playing = bool(getattr(self.app, 'is_playback_active', False))
                except Exception:
                    is_playing = False
                if is_playing and text == 'Play':
                    try:
                        btn.state(['disabled'])
                    except Exception:
                        try:
                            btn.configure(state='disabled')
                        except Exception:
                            pass
        # Ensure current state is reflected after creating buttons
        try:
            self._update_play_button_state()
        except Exception:
            pass

    def _on_status_change(self, *args):
        """Update Play button state when status changes."""
        try:
            self._update_play_button_state()
        except Exception:
            pass

    def _update_play_button_state(self):
        try:
            is_playing = bool(getattr(self.app, 'is_playback_active', False))
        except Exception:
            is_playing = False
        for btn in list(getattr(self, '_play_buttons', []) or []):
            try:
                if hasattr(btn, 'state'):
                    # ttk.Button
                    if is_playing:
                        btn.state(['disabled'])
                    else:
                        btn.state(['!disabled'])
                else:
                    # tk.Button
                    btn.configure(state=('disabled' if is_playing else 'normal'))
            except Exception:
                pass

    def _has_actions_to_save(self) -> bool:
        """Return True if there are recorded actions for the current playlist name in SQLite."""
        try:
            name = ''
            try:
                if getattr(self.app, 'recording_name_var', None):
                    name = (self.app.recording_name_var.get() or '').strip()
            except Exception:
                name = ''
            if not name:
                try:
                    if getattr(self.app, 'selected_playlist', None):
                        name = (self.app.selected_playlist.get() or '').strip()
                except Exception:
                    name = ''
            if not name or name in ('Select playlist', 'No playlists found'):
                return False
            import db as _db
            conn = _db.get_connection()
            cur = conn.cursor()
            cur.execute('SELECT id FROM Playlists WHERE name = ?', (name,))
            row = cur.fetchone()
            if not row:
                conn.close()
                return False
            local_id = row[0]
            total = 0
            try:
                cur.execute('SELECT COUNT(*) FROM Clicks WHERE playlist_id = ?', (local_id,))
                total += int(cur.fetchone()[0])
            except Exception:
                pass
            try:
                cur.execute('SELECT COUNT(*) FROM KeyboardEvents WHERE playlist_id = ?', (local_id,))
                total += int(cur.fetchone()[0])
            except Exception:
                pass
            try:
                cur.execute('SELECT COUNT(*) FROM ActionTriggers WHERE playlist_id = ?', (local_id,))
                total += int(cur.fetchone()[0])
            except Exception:
                pass
            conn.close()
            return total > 0
        except Exception:
            return False

    def _create_live_clicks_view(self):
        """Create the live clicks view card."""
        live_card = tk.Frame(
            self.app._main_frame,
            bg=CARD_BACKGROUND,
            bd=0,
            highlightthickness=1,
            highlightbackground=BORDER_COLOR
        )
        live_card.pack(padx=30, pady=(0, 10), fill='x')
        
        tk.Label(
            live_card,
            text='Live Clicks',
            font=FONT,
            bg=CARD_BACKGROUND,
            fg=TEXT_COLOR
        ).pack(anchor='w', padx=10, pady=(10, 0))
        
        self.app.live_clicks_text = tk.Text(
            live_card,
            height=5,
            bg='#f8f9fa',
            fg=TEXT_COLOR,
            font=FONT,
            state='disabled',
            relief='flat',
            bd=0
        )
        self.app.live_clicks_text.pack(padx=10, pady=(0, 10), fill='x')

    def _apply_styles(self):
        """Apply custom styles to ttk widgets."""
        style = ttk.Style(self.app)
        style.theme_use('clam')
        
        # Button styles
        style.configure('TButton', font=FONT, padding=6, relief='flat')
        style.configure('Dark.TButton', background='#495057', foreground='#fff')
        style.map(
            'Dark.TButton',
            background=[('disabled', '#6c757d'), ('active', '#343a40')],
            foreground=[('disabled', '#d9dde1'), ('active', '#fff')]
        )
        style.configure('Red.TButton', background='#dc3545', foreground='#fff')
        style.map(
            'Red.TButton',
            background=[('disabled', '#adb5bd'), ('active', '#b52a37')],
            foreground=[('disabled', '#f1f3f5'), ('active', '#fff')]
        )
        
        # Combobox styles
        style.configure('TCombobox', fieldbackground='#fff', background='#fff', foreground=TEXT_COLOR)