"""Status setup fullscreen plugin for configuring status area layout.

Provides a fullscreen configuration interface with 4 navigation levels:
- Level 1: Row selection
- Level 2: Widget selection within a row
- Level 3: Widget options (delete, configure, move)
- Level 4: Widget picker (add new widget)
"""

import logging
from enum import Enum
from typing import List, Optional, Any, Dict

from core.fullscreen import FullScreenPlugin
from core.fullscreen.plugin import PluginMetadata
from core.io.key_parser import KeyPress
from core.io.status import (
    StatusWidgetRegistry,
    StatusLayoutManager,
    StatusLayoutRenderer,
    WidgetCategory,
)
from core.ui.design_system import T, S, solid, solid_fg, TagBox

logger = logging.getLogger(__name__)


class NavigationLevel(Enum):
    """Current navigation level in the status setup UI."""
    ROW_SELECTION = 1
    WIDGET_SELECTION = 2
    WIDGET_OPTIONS = 3
    WIDGET_PICKER = 4


class StatusSetupPlugin(FullScreenPlugin):
    """Fullscreen plugin for configuring status area layout."""

    def __init__(self):
        """Initialize the status setup plugin."""
        metadata = PluginMetadata(
            name="status-setup",
            description="Configure status area layout",
            version="1.0.0",
            author="Kollabor",
            category="system",
            icon="[CFG]",
            aliases=["status-config", "status-edit"]
        )
        super().__init__(metadata)

        # Very low FPS for static UI - only need to render on input
        self.target_fps = 1.0

        # Navigation state
        self.nav_level = NavigationLevel.ROW_SELECTION
        self.selected_row = 0
        self.selected_widget = 0
        self.selected_option = 0
        self.picker_category = 0
        self.picker_selection = 0

        # Widget system references (set by set_managers)
        self.widget_registry: Optional[StatusWidgetRegistry] = None
        self.layout_manager: Optional[StatusLayoutManager] = None
        self.layout_renderer: Optional[StatusLayoutRenderer] = None

        # State
        self.dirty = False
        self.message = ""
        self.message_timer = 0

        # Exit prompt state
        self.exit_prompt_active = False
        self.exit_prompt_selection = 0  # 0=Yes, 1=No, 2=Cancel

    def set_managers(self, config, profile_manager):
        """Set manager references from the application.

        Called by FullScreenCommandIntegrator when creating the plugin.
        """
        # We need to get widget system from app - this is passed via config
        if hasattr(config, '_app'):
            app = config._app
            self.widget_registry = getattr(app, 'widget_registry', None)
            self.layout_manager = getattr(app, 'layout_manager', None)
            self.layout_renderer = getattr(app, 'layout_renderer', None)

    def set_widget_system(self, registry, layout_mgr, layout_renderer):
        """Directly set widget system references."""
        self.widget_registry = registry
        self.layout_manager = layout_mgr
        self.layout_renderer = layout_renderer

    async def on_start(self):
        """Called when plugin is started."""
        await super().on_start()
        logger.info(f"StatusSetupPlugin started")

        # Load layout if not already loaded
        if self.layout_manager:
            self.layout_manager.load()

        # Reset navigation state to defaults
        self.nav_level = NavigationLevel.ROW_SELECTION
        self.selected_row = 0
        self.selected_widget = 0
        self.selected_option = 0
        self.picker_category = 0
        self.picker_selection = 0

    async def on_stop(self):
        """Called when plugin is stopped."""
        await super().on_stop()

        if self.dirty:
            logger.warning("StatusSetupPlugin stopped with unsaved changes")

        logger.info(f"StatusSetupPlugin stopped")

    async def render_frame(self, delta_time: float) -> bool:
        """Render the status setup UI using design system."""
        if not self.renderer:
            return False

        # Update message timer
        if self.message_timer > 0:
            self.message_timer -= delta_time
            if self.message_timer <= 0:
                self.message = ""

        self.renderer.clear_screen()
        width, height = self.renderer.get_terminal_size()
        theme = T()

        # Title bar with solid blocks
        self.renderer.write_at(0, 0, solid_fg("▄" * width, theme.primary[0]), "")
        title = "   Status Setup"
        title_padded = f"{title:<{width}}"
        self.renderer.write_at(0, 1, solid(title_padded, theme.primary[0], theme.text, width), "")
        self.renderer.write_at(0, 2, solid_fg("▀" * width, theme.primary[0]), "")

        # Live preview section
        self._render_preview(width, 4)

        # Main content based on navigation level
        content_y = 12
        if self.nav_level == NavigationLevel.ROW_SELECTION:
            self._render_row_selection(width, content_y)
        elif self.nav_level == NavigationLevel.WIDGET_SELECTION:
            self._render_widget_selection(width, content_y)
        elif self.nav_level == NavigationLevel.WIDGET_OPTIONS:
            self._render_widget_options(width, content_y)
        elif self.nav_level == NavigationLevel.WIDGET_PICKER:
            self._render_widget_picker(width, content_y)

        # Footer with controls
        self._render_footer(width, height)

        # Status message
        if self.message:
            self.renderer.write_at(2, height - 4, self.message, "")

        # Exit prompt overlay
        if self.exit_prompt_active:
            self._render_exit_prompt(width, height)

        return True

    def _render_section_header(self, title: str, width: int, y: int):
        """Render a section header with TagBox."""
        theme = T()
        header = TagBox.render(
            lines=[title],
            tag_bg=theme.dark[0], tag_fg=theme.text_dim, tag_width=3,
            content_colors=theme.dark[0], content_fg=theme.text,
            content_width=width - 4,
            tag_chars=[" ■ "],
            indent="",
            use_gradient=False,
        )
        for i, line in enumerate(header.split('\n')):
            self.renderer.write_at(0, y + i, line, "")

    def _render_preview(self, width: int, y: int):
        """Render live preview of status area."""
        self._render_section_header("Live Preview", width, y)

        if self.layout_renderer and self.layout_manager:
            preview_lines = self.layout_renderer.render_preview()
            for i, line in enumerate(preview_lines[:4]):
                self.renderer.write_at(2, y + 4 + i, line[:width-4], "")

    def _render_row_selection(self, width: int, y: int):
        """Render row selection view using design system."""
        theme = T()

        if not self.layout_manager:
            self.renderer.write_at(4, y + 2, "Widget system not initialized", "\033[31m")
            return

        layout = self.layout_manager.get_layout()
        visible_count = sum(1 for r in layout.rows if r.visible)
        self._render_section_header(f"Rows (visible: {visible_count})", width, y)

        # Content box
        box_y = y + 3
        self.renderer.write_at(0, box_y, solid_fg("▄" * width, theme.dark[0]), "")

        for i, row in enumerate(layout.rows):
            row_y = box_y + 1 + i
            cursor = "▸" if i == self.selected_row else " "

            widgets_str = " ".join(f"[{w.id}]" for w in row.widgets)
            if not widgets_str:
                widgets_str = "[+]"
            else:
                widgets_str += " [+]"

            visibility = "(hidden)" if not row.visible else ""
            line = f"   {cursor}  Row {i + 1}: {widgets_str} {visibility}"

            if i == self.selected_row:
                self.renderer.write_at(0, row_y, solid(line.ljust(width), theme.dark[0], theme.text, width), "")
            else:
                self.renderer.write_at(0, row_y, solid(line.ljust(width), theme.dark[0], theme.text_dim, width), "")

        # Add row option (selectable when < 6 rows)
        if len(layout.rows) < 6:
            add_y = box_y + 1 + len(layout.rows)
            cursor = "▸" if self.selected_row == len(layout.rows) else " "
            add_line = f"   {cursor}  + Add row (up to 6)"

            if self.selected_row == len(layout.rows):
                self.renderer.write_at(0, add_y, solid(add_line.ljust(width), theme.dark[0], theme.primary[0], width), "")
            else:
                self.renderer.write_at(0, add_y, solid(add_line.ljust(width), theme.dark[0], theme.text_dim, width), "")
            separator_y = add_y + 1
        else:
            separator_y = box_y + 1 + len(layout.rows)

        # Separator
        self.renderer.write_at(0, separator_y, solid_fg("▀" * width, theme.dark[0]), "")
        self.renderer.write_at(4, separator_y + 1, "---" + " " * (width - 7), "")

        # Calculate option indices for restore/reset
        if len(layout.rows) < 6:
            restore_idx = len(layout.rows) + 1
            reset_idx = len(layout.rows) + 2
        else:
            restore_idx = len(layout.rows)
            reset_idx = len(layout.rows) + 1

        # Restore previous layout option (if backup exists)
        if layout.backup:
            restore_y = separator_y + 2
            cursor = "▸" if self.selected_row == restore_idx else " "
            restore_line = f"   {cursor}  Restore previous layout"

            if self.selected_row == restore_idx:
                self.renderer.write_at(0, restore_y, solid(restore_line.ljust(width), theme.dark[0], theme.primary[0], width), "")
            else:
                self.renderer.write_at(0, restore_y, solid(restore_line.ljust(width), theme.dark[0], theme.text_dim, width), "")

        # Reset to default option
        reset_y = separator_y + 3 if layout.backup else separator_y + 2
        cursor = "▸" if self.selected_row == reset_idx else " "
        reset_line = f"   {cursor}  Reset to default"

        if self.selected_row == reset_idx:
            self.renderer.write_at(0, reset_y, solid(reset_line.ljust(width), theme.dark[0], theme.error, width), "")
        else:
            self.renderer.write_at(0, reset_y, solid(reset_line.ljust(width), theme.dark[0], theme.text_dim, width), "")

        self.renderer.write_at(0, reset_y + 1, solid_fg("▀" * width, theme.dark[0]), "")

    def _render_widget_selection(self, width: int, y: int):
        """Render widget selection within a row using design system."""
        theme = T()

        if not self.layout_manager:
            return

        row = self.layout_manager.get_layout().rows[self.selected_row]
        self._render_section_header(f"Row {self.selected_row + 1} Widgets", width, y)

        # Content box
        box_y = y + 3
        self.renderer.write_at(0, box_y, solid_fg("▄" * width, theme.dark[0]), "")

        for i, widget in enumerate(row.widgets):
            widget_y = box_y + 1 + i
            cursor = "▸" if i == self.selected_widget else " "
            line = f"   {cursor}  [{widget.id}] width: {widget.width or 'auto'}"

            if i == self.selected_widget:
                self.renderer.write_at(0, widget_y, solid(line.ljust(width), theme.dark[0], theme.text, width), "")
            else:
                self.renderer.write_at(0, widget_y, solid(line.ljust(width), theme.dark[0], theme.text_dim, width), "")

        # Add widget option
        add_idx = len(row.widgets)
        add_y = box_y + 1 + add_idx
        cursor = "▸" if self.selected_widget == add_idx else " "
        add_line = f"   {cursor}  [+] Add widget"

        if self.selected_widget == add_idx:
            self.renderer.write_at(0, add_y, solid(add_line.ljust(width), theme.dark[0], theme.primary[0], width), "")
        else:
            self.renderer.write_at(0, add_y, solid(add_line.ljust(width), theme.dark[0], theme.text_dim, width), "")

        self.renderer.write_at(0, add_y + 1, solid_fg("▀" * width, theme.dark[0]), "")

    def _render_widget_options(self, width: int, y: int):
        """Render widget options menu using design system."""
        theme = T()

        if not self.layout_manager:
            return

        row = self.layout_manager.get_layout().rows[self.selected_row]
        widget = row.widgets[self.selected_widget]

        self._render_section_header(f"Widget: {widget.id}", width, y)

        # Content box
        box_y = y + 3
        self.renderer.write_at(0, box_y, solid_fg("▄" * width, theme.dark[0]), "")

        options = ["Delete", "Move left", "Move right", "Change width"]
        for i, opt in enumerate(options):
            opt_y = box_y + 1 + i
            cursor = "▸" if i == self.selected_option else " "
            line = f"   {cursor}  {opt}"

            if i == self.selected_option:
                self.renderer.write_at(0, opt_y, solid(line.ljust(width), theme.dark[0], theme.text, width), "")
            else:
                self.renderer.write_at(0, opt_y, solid(line.ljust(width), theme.dark[0], theme.text_dim, width), "")

        self.renderer.write_at(0, box_y + 1 + len(options), solid_fg("▀" * width, theme.dark[0]), "")

    def _render_widget_picker(self, width: int, y: int):
        """Render widget picker using design system."""
        theme = T()

        self._render_section_header("Add Widget", width, y)

        if not self.widget_registry:
            self.renderer.write_at(4, y + 4, "No widgets available", "")
            return

        # Get available widgets
        all_widgets = self.widget_registry.get_all()
        categories = ["core", "plugin"]

        # Category tabs box
        box_y = y + 3
        self.renderer.write_at(0, box_y, solid_fg("▄" * width, theme.dark[0]), "")

        for i, cat in enumerate(categories):
            cat_y = box_y + 1 + i
            cursor = "▸" if i == self.picker_category else " "
            line = f"   {cursor}  {cat.upper()}"

            if i == self.picker_category:
                self.renderer.write_at(0, cat_y, solid(line.ljust(width), theme.dark[0], theme.text, width), "")
            else:
                self.renderer.write_at(0, cat_y, solid(line.ljust(width), theme.dark[0], theme.text_dim, width), "")

        self.renderer.write_at(0, box_y + 1 + len(categories), solid_fg("▀" * width, theme.dark[0]), "")

        # Widgets list box
        widget_box_y = box_y + len(categories) + 3
        cat_filter = WidgetCategory.CORE if self.picker_category == 0 else WidgetCategory.PLUGIN
        filtered = [w for w in all_widgets if w.category == cat_filter]

        self.renderer.write_at(0, widget_box_y, solid_fg("▄" * width, theme.dark[0]), "")

        for i, widget in enumerate(filtered[:10]):
            widget_y = widget_box_y + 1 + i
            cursor = "▸" if i == self.picker_selection else " "
            line = f"   {cursor}  {widget.id}: {widget.name}"

            if i == self.picker_selection:
                self.renderer.write_at(0, widget_y, solid(line.ljust(width), theme.dark[0], theme.primary[0], width), "")
            else:
                self.renderer.write_at(0, widget_y, solid(line.ljust(width), theme.dark[0], theme.text_dim, width), "")

        list_height = min(len(filtered), 10)
        self.renderer.write_at(0, widget_box_y + 1 + list_height, solid_fg("▀" * width, theme.dark[0]), "")

    def _render_footer(self, width: int, height: int):
        """Render footer with navigation hints using design system."""
        theme = T()
        footer_y = height - 2

        if self.nav_level == NavigationLevel.ROW_SELECTION:
            hints = "Up/Down: navigate | Enter: edit row | v: toggle visible | Esc: exit"
        elif self.nav_level == NavigationLevel.WIDGET_SELECTION:
            hints = "Up/Down: navigate | Enter: options/add | Esc: back"
        elif self.nav_level == NavigationLevel.WIDGET_OPTIONS:
            hints = "Up/Down: navigate | Enter: select | Esc: back"
        elif self.nav_level == NavigationLevel.WIDGET_PICKER:
            hints = "Up/Down: navigate | Left/Right: category | Enter: add | Esc: back"
        else:
            hints = "Esc: exit"

        # Footer bar with solid blocks
        self.renderer.write_at(0, footer_y, solid_fg("▄" * width, theme.dark[0]), "")
        hints_padded = f"   {hints:<{width-3}}"
        self.renderer.write_at(0, footer_y + 1, solid(hints_padded, theme.dark[0], theme.text_dim, width), "")

    async def handle_input(self, key_press: KeyPress) -> bool:
        """Handle keyboard input."""
        # Exit prompt takes priority
        if self.exit_prompt_active:
            return await self._handle_exit_prompt_input(key_press)

        # Global: Ctrl+S to save
        if key_press.modifiers.get('ctrl') and key_press.char == 's':
            self._save()
            self.message = "Saved!"
            self.message_timer = 2.0
            return False

        # Escape handling
        if key_press.name == "Escape" or key_press.char == '\x1b':
            if self.nav_level == NavigationLevel.ROW_SELECTION:
                # Check for unsaved changes before exiting
                if self.dirty:
                    self.exit_prompt_active = True
                    self.exit_prompt_selection = 0
                    return False
                return True  # Exit plugin
            else:
                # Go back one level
                if self.nav_level == NavigationLevel.WIDGET_PICKER:
                    self.nav_level = NavigationLevel.WIDGET_SELECTION
                elif self.nav_level == NavigationLevel.WIDGET_OPTIONS:
                    self.nav_level = NavigationLevel.WIDGET_SELECTION
                elif self.nav_level == NavigationLevel.WIDGET_SELECTION:
                    self.nav_level = NavigationLevel.ROW_SELECTION
                return False

        # Route to level-specific handler
        if self.nav_level == NavigationLevel.ROW_SELECTION:
            return await self._handle_row_input(key_press)
        elif self.nav_level == NavigationLevel.WIDGET_SELECTION:
            return await self._handle_widget_input(key_press)
        elif self.nav_level == NavigationLevel.WIDGET_OPTIONS:
            return await self._handle_options_input(key_press)
        elif self.nav_level == NavigationLevel.WIDGET_PICKER:
            return await self._handle_picker_input(key_press)

        return False

    async def _handle_row_input(self, key_press: KeyPress) -> bool:
        """Handle input in row selection mode."""
        if not self.layout_manager:
            return False

        layout = self.layout_manager.get_layout()
        # Calculate max selectable index:
        # - rows (len(layout.rows))
        # - +1 for add option when < 6 rows
        # - +1 for restore option if backup exists
        # - +1 for reset option (always present)
        max_rows = len(layout.rows)
        max_rows += 1 if len(layout.rows) < 6 else 0  # add option
        max_rows += 1 if layout.backup else 0  # restore option
        max_rows += 1  # reset option (always present)

        # Handle empty layout - prevent navigation crashes
        if len(layout.rows) == 0:
            self.selected_row = 0
            return False

        if key_press.name == "ArrowUp":
            self.selected_row = max(0, self.selected_row - 1)
        elif key_press.name == "ArrowDown":
            self.selected_row = min(max_rows - 1, self.selected_row + 1)
        elif key_press.name == "Enter" or key_press.char in ['\r', '\n']:
            # Calculate restore/reset indices (same logic as render)
            if len(layout.rows) < 6:
                restore_idx = len(layout.rows) + 1
                reset_idx = len(layout.rows) + 2
            else:
                restore_idx = len(layout.rows)
                reset_idx = len(layout.rows) + 1

            # Handle restore option
            if layout.backup and self.selected_row == restore_idx:
                success = self.layout_manager.restore_backup()
                if success:
                    self.message = "Layout restored!"
                    self.message_timer = 2.0
                    self.dirty = True
                else:
                    self.message = "Restore failed!"
                    self.message_timer = 2.0
            # Handle reset option
            elif self.selected_row == reset_idx:
                success = self.layout_manager.reset_to_default()
                if success:
                    self.message = "Layout reset to default!"
                    self.message_timer = 2.0
                    self.dirty = True
                else:
                    self.message = "Reset failed!"
                    self.message_timer = 2.0
            # Check if add option is selected
            elif self.selected_row == len(layout.rows):
                # Add new row
                new_row_id = self.layout_manager.add_new_row()
                if new_row_id is not None:
                    self.dirty = True
                    self.message = "Row added!"
                    self.message_timer = 2.0
            else:
                # Edit existing row
                self.nav_level = NavigationLevel.WIDGET_SELECTION
                self.selected_widget = 0
        elif key_press.char == 'v':
            # Toggle visibility (only works on actual rows, not add option)
            if self.selected_row < len(layout.rows):
                layout.rows[self.selected_row].visible = not layout.rows[self.selected_row].visible
                self.dirty = True
        elif key_press.char == 'q':
            return True

        return False

    async def _handle_widget_input(self, key_press: KeyPress) -> bool:
        """Handle input in widget selection mode."""
        if not self.layout_manager:
            return False

        layout = self.layout_manager.get_layout()
        # Validate selected_row bounds
        if self.selected_row >= len(layout.rows):
            self.selected_row = max(0, len(layout.rows) - 1)
            self.selected_widget = 0
            return False

        row = layout.rows[self.selected_row]
        max_widgets = len(row.widgets) + 1  # +1 for add option

        if key_press.name == "ArrowUp":
            self.selected_widget = max(0, self.selected_widget - 1)
        elif key_press.name == "ArrowDown":
            self.selected_widget = min(max_widgets - 1, self.selected_widget + 1)
        elif key_press.name == "Enter" or key_press.char in ['\r', '\n']:
            if self.selected_widget == len(row.widgets):
                # Add widget
                self.nav_level = NavigationLevel.WIDGET_PICKER
                self.picker_selection = 0
            else:
                # Edit widget
                self.nav_level = NavigationLevel.WIDGET_OPTIONS
                self.selected_option = 0

        return False

    async def _handle_options_input(self, key_press: KeyPress) -> bool:
        """Handle input in widget options mode."""
        if not self.layout_manager:
            return False

        options = ["delete", "move_left", "move_right", "width"]

        if key_press.name == "ArrowUp":
            self.selected_option = max(0, self.selected_option - 1)
        elif key_press.name == "ArrowDown":
            self.selected_option = min(len(options) - 1, self.selected_option + 1)
        elif key_press.name == "Enter" or key_press.char in ['\r', '\n']:
            action = options[self.selected_option]
            layout = self.layout_manager.get_layout()

            # Validate selected_row bounds before accessing
            if self.selected_row >= len(layout.rows):
                self.nav_level = NavigationLevel.ROW_SELECTION
                self.selected_row = max(0, len(layout.rows) - 1)
                return False

            row = layout.rows[self.selected_row]

            if action == "delete":
                row.widgets.pop(self.selected_widget)
                self.dirty = True
                self.nav_level = NavigationLevel.WIDGET_SELECTION
                self.selected_widget = min(self.selected_widget, len(row.widgets))
            elif action == "move_left" and self.selected_widget > 0:
                widgets = row.widgets
                widgets[self.selected_widget], widgets[self.selected_widget - 1] = \
                    widgets[self.selected_widget - 1], widgets[self.selected_widget]
                self.selected_widget -= 1
                self.dirty = True
            elif action == "move_right" and self.selected_widget < len(row.widgets) - 1:
                widgets = row.widgets
                widgets[self.selected_widget], widgets[self.selected_widget + 1] = \
                    widgets[self.selected_widget + 1], widgets[self.selected_widget]
                self.selected_widget += 1
                self.dirty = True

        return False

    async def _handle_picker_input(self, key_press: KeyPress) -> bool:
        """Handle input in widget picker mode."""
        if not self.widget_registry or not self.layout_manager:
            logger.warning("Widget registry or layout manager not set")
            return False

        all_widgets = self.widget_registry.get_all()
        cat_filter = WidgetCategory.CORE if self.picker_category == 0 else WidgetCategory.PLUGIN
        filtered = [w for w in all_widgets if w.category == cat_filter]
        logger.debug(f"Picker: {len(all_widgets)} total widgets, {len(filtered)} in category {cat_filter}")

        # Handle empty list case - reset selection to 0 and ignore navigation
        if not filtered:
            self.picker_selection = 0
            return False

        if key_press.name == "ArrowUp":
            self.picker_selection = max(0, self.picker_selection - 1)
        elif key_press.name == "ArrowDown":
            self.picker_selection = min(len(filtered) - 1, self.picker_selection + 1)
        elif key_press.name == "ArrowLeft":
            self.picker_category = 0
            self.picker_selection = 0
        elif key_press.name == "ArrowRight":
            self.picker_category = 1
            self.picker_selection = 0
        elif key_press.name == "Enter" or key_press.char in ['\r', '\n']:
            if filtered and self.picker_selection < len(filtered):
                widget = filtered[self.picker_selection]
                from core.io.status.layout_manager import WidgetConfig
                row = self.layout_manager.get_layout().rows[self.selected_row]
                row.widgets.append(WidgetConfig(id=widget.id))
                self.layout_manager.mark_dirty()  # Mark layout manager as dirty
                self.dirty = True
                self.nav_level = NavigationLevel.WIDGET_SELECTION
                self.selected_widget = len(row.widgets) - 1
                logger.info(f"Added widget {widget.id} to row {self.selected_row}")

        return False

    def _save(self) -> bool:
        """Save current layout configuration."""
        if self.layout_manager:
            success = self.layout_manager.save()
            if success:
                self.dirty = False
                logger.info("Status layout saved")
            return success
        return False

    def _render_exit_prompt(self, width: int, height: int):
        """Render exit confirmation dialog overlay using TagBox."""
        theme = T()

        # Dialog dimensions
        dialog_width = 40
        dialog_height = 8
        dialog_x = (width - dialog_width) // 2
        dialog_y = (height - dialog_height) // 2

        # Dialog content lines
        content_lines = ["Save changes?", ""]

        # Options with selection indicator
        options = ["Yes", "No", "Cancel"]
        option_lines = []
        for i, opt in enumerate(options):
            cursor = "▸ " if i == self.exit_prompt_selection else "  "
            option_lines.append(f"{cursor}{opt}")

        # Build complete dialog content
        dialog_content = content_lines + option_lines

        # Render dialog using TagBox
        dialog = TagBox.render(
            lines=dialog_content,
            tag_bg=theme.primary[0], tag_fg=theme.text_dark, tag_width=3,
            content_colors=theme.dark[0], content_fg=theme.text,
            content_width=dialog_width - 4,
            tag_chars=[" ! "] + ["   "] * (len(dialog_content) - 1),
            indent="",
            use_gradient=False,
        )

        # Write dialog at centered position
        for i, line in enumerate(dialog.split('\n')):
            self.renderer.write_at(dialog_x, dialog_y + i, line, "")

    async def _handle_exit_prompt_input(self, key_press: KeyPress) -> bool:
        """Handle input in exit confirmation dialog."""
        if key_press.name == "ArrowUp":
            self.exit_prompt_selection = max(0, self.exit_prompt_selection - 1)
        elif key_press.name == "ArrowDown":
            self.exit_prompt_selection = min(2, self.exit_prompt_selection + 1)
        elif key_press.name == "Enter" or key_press.char in ['\r', '\n']:
            # Execute selected option
            if self.exit_prompt_selection == 0:  # Yes
                self._save()
                self.message = "Saved!"
                self.message_timer = 2.0
                self.exit_prompt_active = False
                return True  # Exit plugin
            elif self.exit_prompt_selection == 1:  # No
                self.exit_prompt_active = False
                return True  # Exit plugin without saving
            else:  # Cancel
                self.exit_prompt_active = False
                return False  # Don't exit
        elif key_press.name == "Escape" or key_press.char == '\x1b':
            # Cancel on escape
            self.exit_prompt_active = False
            return False
        elif key_press.char.lower() == 'y':
            # Yes shortcut
            self._save()
            self.message = "Saved!"
            self.message_timer = 2.0
            self.exit_prompt_active = False
            return True  # Exit plugin
        elif key_press.char.lower() == 'n':
            # No shortcut
            self.exit_prompt_active = False
            return True  # Exit plugin without saving
        elif key_press.char.lower() == 'c':
            # Cancel shortcut
            self.exit_prompt_active = False
            return False  # Don't exit

        return False
