"""Resume conversation plugin for session management."""

import logging
from datetime import datetime
from typing import Dict, Any, List, Optional
from pathlib import Path

from core.events.models import CommandDefinition, CommandMode, CommandCategory, CommandResult, SlashCommand, UIConfig, Event
from core.models.resume import SessionMetadata, SessionSummary, ConversationMetadata
from core.io.visual_effects import AgnosterSegment

logger = logging.getLogger(__name__)


class ResumeConversationPlugin:
    """Plugin for resuming previous conversations."""

    def __init__(self, **kwargs) -> None:
        """Initialize the resume conversation plugin."""
        self.name = "resume_conversation"
        self.version = "1.0.0"
        self.description = "Resume previous conversation sessions"
        self.enabled = True
        self.logger = logger
        
        # Dependencies (will be injected during initialization)
        self.conversation_manager = None
        self.conversation_logger = None
        self.event_bus = None
        self.config = None
        self.llm_service = None
        self.renderer = None

    async def initialize(self, event_bus, config, **kwargs) -> None:
        """Initialize the plugin and register commands.

        Args:
            event_bus: Application event bus.
            config: Configuration manager.
            **kwargs: Additional initialization parameters.
        """
        try:
            self.event_bus = event_bus
            self.config = config
            
            # Get dependencies from kwargs
            self.conversation_manager = kwargs.get('conversation_manager')
            self.conversation_logger = kwargs.get('conversation_logger')
            self.llm_service = kwargs.get('llm_service')
            self.renderer = kwargs.get('renderer')
            
            # Get command registry
            command_registry = kwargs.get('command_registry')
            if not command_registry:
                self.logger.warning("No command registry provided, resume commands not registered")
                return

            # Register resume command
            self._register_resume_commands(command_registry)

            # Register status view
            await self._register_status_view()

            self.logger.info("Resume conversation plugin initialized successfully")

        except Exception as e:
            self.logger.error(f"Error initializing resume conversation plugin: {e}")
            raise

    async def _register_status_view(self) -> None:
        """Register resume conversation status view."""
        try:
            if (self.renderer and
                hasattr(self.renderer, 'status_renderer') and
                self.renderer.status_renderer and
                hasattr(self.renderer.status_renderer, 'status_registry') and
                self.renderer.status_renderer.status_registry):

                from core.io.status_renderer import StatusViewConfig, BlockConfig

                view = StatusViewConfig(
                    name="Resume",
                    plugin_source="resume_conversation",
                    priority=290,
                    blocks=[BlockConfig(
                        width_fraction=1.0,
                        content_provider=self._get_status_content,
                        title="Resume",
                        priority=100
                    )],
                )

                registry = self.renderer.status_renderer.status_registry
                registry.register_status_view("resume_conversation", view)
                self.logger.info("Registered 'Resume' status view")

        except Exception as e:
            self.logger.error(f"Failed to register status view: {e}")

    def _get_status_content(self) -> List[str]:
        """Get resume conversation status (agnoster style)."""
        try:
            seg = AgnosterSegment()
            seg.add_lime("Resume", "dark")
            seg.add_cyan("/resume", "dark")
            seg.add_neutral("restore previous sessions", "mid")
            return [seg.render()]

        except Exception as e:
            self.logger.error(f"Error getting status content: {e}")
            seg = AgnosterSegment()
            seg.add_neutral("Resume: Error", "dark")
            return [seg.render()]

    def _register_resume_commands(self, command_registry) -> None:
        """Register resume-related commands.

        Args:
            command_registry: Command registry for registration.
        """
        try:
            # Main resume command
            resume_command = CommandDefinition(
                name="resume",
                description="Resume a previous conversation session",
                handler=self.handle_resume,
                plugin_name=self.name,
                category=CommandCategory.CONVERSATION,
                mode=CommandMode.STATUS_TAKEOVER,
                aliases=["restore", "continue"],
                icon="[⏯]",
                ui_config=UIConfig(
                    type="modal",
                    title="Resume Conversation",
                    height=20,
                    width=80
                )
            )
            command_registry.register_command(resume_command)
            
            # Session search command
            search_command = CommandDefinition(
                name="sessions",
                description="Search and browse conversation sessions",
                handler=self.handle_sessions,
                plugin_name=self.name,
                category=CommandCategory.CONVERSATION,
                mode=CommandMode.STATUS_TAKEOVER,
                aliases=["history", "conversations"],
                icon="[s]",
                ui_config=UIConfig(
                    type="modal",
                    title="Conversation History",
                    height=20,
                    width=80
                )
            )
            command_registry.register_command(search_command)

            # Branch command
            branch_command = CommandDefinition(
                name="branch",
                description="Branch conversation from a specific message",
                handler=self.handle_branch,
                plugin_name=self.name,
                category=CommandCategory.CONVERSATION,
                mode=CommandMode.STATUS_TAKEOVER,
                aliases=["fork"],
                icon="[⑂]",
                ui_config=UIConfig(
                    type="modal",
                    title="Branch Conversation",
                    height=20,
                    width=80
                )
            )
            command_registry.register_command(branch_command)

        except Exception as e:
            self.logger.error(f"Error registering resume commands: {e}")

    async def handle_resume(self, command: SlashCommand) -> CommandResult:
        """Handle /resume command.

        Args:
            command: Parsed slash command.

        Returns:
            Command execution result.
        """
        try:
            args = command.args or []
            force = False
            if args:
                force = "--force" in args
                args = [arg for arg in args if arg != "--force"]
            
            if len(args) == 0:
                # Show session selection modal
                return await self._show_conversation_menu()
            elif len(args) == 1:
                # Resume specific session by ID
                session_id = args[0]
                return await self._load_conversation(session_id, force=force)
            elif len(args) >= 2 and args[0].lower() == "search":
                # Search sessions
                query = " ".join(args[1:])
                return await self._search_conversations(query)
            else:
                # Handle filters and other options
                return await self._handle_resume_options(args)

        except Exception as e:
            self.logger.error(f"Error in resume command: {e}")
            return CommandResult(
                success=False,
                message=f"Error resuming conversation: {str(e)}",
                display_type="error"
            )

    async def handle_sessions(self, command: SlashCommand) -> CommandResult:
        """Handle /sessions command.

        Args:
            command: Parsed slash command.

        Returns:
            Command execution result.
        """
        try:
            args = command.args or []
            
            if len(args) == 0:
                # Show all sessions
                return await self._show_conversation_menu()
            elif args[0].lower() == "search":
                if len(args) > 1:
                    query = " ".join(args[1:])
                    return await self._search_conversations(query)
                else:
                    return CommandResult(
                        success=False,
                        message="Usage: /sessions search <query>",
                        display_type="error"
                    )
            else:
                return CommandResult(
                    success=False,
                    message="Usage: /sessions [search <query>]",
                    display_type="error"
                )

        except Exception as e:
            self.logger.error(f"Error in sessions command: {e}")
            return CommandResult(
                success=False,
                message=f"Error browsing sessions: {str(e)}",
                display_type="error"
            )

    async def handle_branch(self, command: SlashCommand) -> CommandResult:
        """Handle /branch command for branching conversations.

        Creates a new branch from any conversation at any message point.
        Original conversation remains intact, new branch is created.

        Usage:
            /branch                    - Show sessions to branch from
            /branch <session_id>       - Show messages to select branch point
            /branch <session_id> <idx> - Create branch from message at index

        Args:
            command: Parsed slash command.

        Returns:
            Command execution result.
        """
        try:
            args = command.args or []

            if not self._ensure_conversation_manager():
                return CommandResult(success=False, message="Conversation manager not available", display_type="error")

            if len(args) == 0:
                # Step 1: Show sessions to branch from (including current)
                return await self._show_branch_session_selector()

            elif len(args) == 1:
                # Step 2: Show messages from session to select branch point
                session_id = args[0]
                return await self._show_branch_point_selector(session_id)

            elif len(args) >= 2:
                # Step 3: Execute the branch - create new session from branch point
                session_id = args[0]
                self.logger.info(f"[BRANCH] Step 3: Execute branch from session={session_id}")
                try:
                    branch_index = int(args[1])
                except ValueError:
                    self.logger.error(f"[BRANCH] Invalid branch index: {args[1]}")
                    return CommandResult(
                        success=False,
                        message=f"Invalid branch index: {args[1]}. Must be a number.",
                        display_type="error"
                    )

                self.logger.info(f"[BRANCH] Executing branch at index {branch_index}")
                # Create branch and load it
                result = await self._execute_branch_from_session(session_id, branch_index)
                self.logger.info(f"[BRANCH] Result: success={result.success}, message={result.message[:50]}...")
                return result

        except Exception as e:
            self.logger.error(f"Error in branch command: {e}")
            return CommandResult(
                success=False,
                message=f"Error branching conversation: {str(e)}",
                display_type="error"
            )

    async def _execute_branch_from_session(self, session_id: str, branch_index: int) -> CommandResult:
        """Execute branch operation - create new session from branch point and load it.

        Args:
            session_id: Source session to branch from (or "current" for active conversation).
            branch_index: Index to branch from (inclusive).

        Returns:
            Command result.
        """
        try:
            # Handle current conversation
            if session_id == "current":
                if not self.llm_service or not hasattr(self.llm_service, 'conversation_history'):
                    return CommandResult(
                        success=False,
                        message="No current conversation available",
                        display_type="error"
                    )

                current_messages = self.llm_service.conversation_history
                if branch_index < 0 or branch_index >= len(current_messages):
                    return CommandResult(
                        success=False,
                        message=f"Invalid index. Must be 0-{len(current_messages)-1}.",
                        display_type="error"
                    )

                # Create branch from current - keep messages up to branch_index
                branched_messages = current_messages[:branch_index + 1]
                self.llm_service.conversation_history = branched_messages

                # Update session stats to reflect truncated messages
                if hasattr(self.llm_service, 'session_stats'):
                    self.llm_service.session_stats["messages"] = len(branched_messages)

                msg_count = len(branched_messages)
                removed_count = len(current_messages) - msg_count

                return CommandResult(
                    success=True,
                    message=f"[ok] Branched at message {branch_index}\n"
                            f"    Kept {msg_count} messages, removed {removed_count}\n"
                            f"    Continue the conversation from this point.",
                    display_type="success"
                )

            # Branch from saved session
            result = self.conversation_manager.branch_session(session_id, branch_index)

            if not result.get("success"):
                return CommandResult(success=False, message=f"Branch failed: {result.get('error', 'Unknown error')}", display_type="error")

            new_session_id = result.get("session_id")
            return await self._load_and_display_session(
                header=f"--- Branched from {session_id} at message {branch_index} ---",
                success_msg=(
                    f"[ok] Created branch: {new_session_id}\n"
                    f"    From: {session_id} at message {result['branch_point']}\n"
                    f"    Loaded {result['message_count']} messages. Continue below."
                )
            )

        except Exception as e:
            self.logger.error(f"Error executing branch: {e}")
            return CommandResult(
                success=False,
                message=f"Error executing branch: {str(e)}",
                display_type="error"
            )

    async def _show_branch_session_selector(self) -> CommandResult:
        """Show modal to select a session to branch from."""
        session_items = []

        # Add current conversation as first option if it has messages
        current_msg_count = 0
        if self.llm_service and hasattr(self.llm_service, 'conversation_history'):
            current_messages = self.llm_service.conversation_history
            current_msg_count = len(current_messages) if current_messages else 0

        if current_msg_count >= 2:
            # Get first user message for preview
            first_user_msg = ""
            for msg in current_messages:
                role = msg.role if hasattr(msg, 'role') else msg.get('role', '')
                content = msg.content if hasattr(msg, 'content') else msg.get('content', '')
                if role == "user" and content:
                    first_user_msg = content[:45].split('\n')[0]
                    if len(content) > 45:
                        first_user_msg += "..."
                    break

            session_items.append({
                "id": "current",
                "title": f"[*CURRENT*] {first_user_msg or 'Active conversation'}",
                "subtitle": f"{current_msg_count} msgs | this session",
                "metadata": {"session_id": "current"},
                "action": "branch_select_session"
            })

        # Add saved conversations
        conversations = await self.discover_conversations(limit=20)

        for conv in conversations:
            time_str = conv.created_time.strftime("%m/%d %H:%M") if conv.created_time else "Unknown"
            project_name = conv.working_directory.split("/")[-1] if conv.working_directory else "unknown"

            # Get user's actual request - skip system prompts
            user_request = ""
            if conv.preview_messages:
                for msg in conv.preview_messages:
                    role = msg.get("role", "")
                    content = msg.get("content", "")
                    # Skip system messages and empty content
                    if role == "system" or not content:
                        continue
                    # Skip if content looks like a system prompt (starts with common prompt markers)
                    content_lower = content.lower()[:50]
                    if any(marker in content_lower for marker in ["you are", "system prompt", "assistant", "kollabor"]):
                        continue
                    if role == "user" and content:
                        user_request = content
                        break

            # Truncate and clean up first line
            if user_request:
                first_line = user_request.split('\n')[0].strip()[:50]
                if len(user_request.split('\n')[0]) > 50:
                    first_line += "..."
            else:
                first_line = f"{conv.message_count} messages"

            session_items.append({
                "id": conv.session_id,
                "title": f"[{time_str}] {first_line}",
                "subtitle": f"{conv.message_count} msgs | {project_name} | {conv.git_branch or '-'}",
                "metadata": {"session_id": conv.session_id},
                "action": "branch_select_session"
            })

        if not session_items:
            return CommandResult(
                success=False,
                message="No conversations found to branch from. Start a conversation first.",
                display_type="info"
            )

        modal_definition = {
            "title": "Branch From Session",
            "footer": "Up/Down navigate | Enter select | Esc cancel",
            # Width is dynamic (terminal_width - 2)
            "height": 20,
            "sections": [
                {
                    "title": f"Select session to branch ({len(session_items)} available)",
                    "type": "session_list",
                    "sessions": session_items
                }
            ]
        }

        return CommandResult(
            success=True,
            message="Select a session to branch from",
            display_type="modal",
            ui_config=UIConfig(
                type="modal",
                title=modal_definition["title"],
                modal_config=modal_definition
            )
        )

    async def _show_branch_point_selector(self, session_id: str) -> CommandResult:
        """Show modal to select branch point message."""
        messages = []

        # Handle current conversation
        if session_id == "current":
            if self.llm_service and hasattr(self.llm_service, 'conversation_history'):
                current_messages = self.llm_service.conversation_history
                for i, msg in enumerate(current_messages or []):
                    role = msg.role if hasattr(msg, 'role') else msg.get('role', 'unknown')
                    content = msg.content if hasattr(msg, 'content') else msg.get('content', '')
                    preview = content[:50].replace('\n', ' ')
                    if len(content) > 50:
                        preview += "..."
                    messages.append({
                        "index": i,
                        "role": role,
                        "preview": preview,
                        "timestamp": None
                    })
            title_text = "Current Session"
        else:
            # Get messages from saved session
            messages = self.conversation_manager.get_session_messages(session_id)
            # Format title - extract readable part from session_id (e.g., "2512301235-shadow-rise" -> "shadow-rise")
            parts = session_id.split("-", 1)
            title_text = parts[1] if len(parts) > 1 else session_id[:12]

        if not messages:
            return CommandResult(
                success=False,
                message=f"No messages found in session: {session_id}",
                display_type="error"
            )

        # Build message selector - skip system messages from display
        message_items = []
        for msg in messages:
            role = msg["role"]
            preview = msg["preview"]

            # Skip system prompt messages from selection (can't meaningfully branch from them)
            if role == "system":
                continue

            # Role indicators and labels
            if role == "user":
                role_indicator = "YOU:"
                role_label = "user"
            else:
                role_indicator = "AI:"
                role_label = "assistant"

            # Clean up preview
            clean_preview = preview.strip()[:55]
            if len(preview) > 55:
                clean_preview += "..."

            # Format timestamp if available
            ts = msg.get('timestamp')
            time_str = ts[11:16] if ts and len(ts) > 16 else ""  # Just HH:MM

            message_items.append({
                "id": str(msg["index"]),
                "title": f"[{msg['index']}] {role_indicator} {clean_preview}",
                "subtitle": f"{role_label}{' | ' + time_str if time_str else ''}",
                "metadata": {
                    "session_id": session_id,
                    "message_index": msg["index"]
                },
                "action": "branch_execute",
                "exit_mode": "minimal"  # Plugin will display content after modal exit
            })

        modal_definition = {
            "title": f"Branch Point: {title_text}",
            "footer": "Up/Down navigate | Enter branch here | Esc cancel",
            # Width is dynamic (terminal_width - 2)
            "height": 20,
            "sections": [
                {
                    "title": f"Select message to branch from ({len(messages)} messages)",
                    "type": "session_list",
                    "sessions": message_items
                }
            ]
        }

        return CommandResult(
            success=True,
            message=f"Select branch point",
            display_type="modal",
            ui_config=UIConfig(
                type="modal",
                title=modal_definition["title"],
                modal_config=modal_definition
            )
        )

    async def discover_conversations(self, limit: int = 50) -> List[ConversationMetadata]:
        """Discover available conversations.

        Args:
            limit: Maximum number of conversations to return

        Returns:
            List of conversation metadata
        """
        conversations = []
        
        try:
            if not self.conversation_logger:
                self.logger.warning("Conversation logger not available")
                return conversations
            
            # Get sessions from conversation logger
            sessions = self.conversation_logger.list_sessions()
            
            for session_data in sessions:
                # Stop if we have enough conversations
                if len(conversations) >= limit:
                    break

                try:
                    # Filter out sessions with 2 or fewer messages
                    message_count = session_data.get("message_count", 0)
                    if message_count <= 2:
                        continue

                    # Strip 'session_' prefix if present for compatibility with conversation_manager
                    raw_session_id = session_data.get("session_id", "")
                    session_id = raw_session_id.replace("session_", "") if raw_session_id.startswith("session_") else raw_session_id

                    metadata = ConversationMetadata(
                        file_path=session_data.get("file_path", ""),
                        session_id=session_id,
                        title=self._generate_session_title(session_data),
                        message_count=message_count,
                        created_time=self._parse_datetime(session_data.get("start_time")),
                        modified_time=self._parse_datetime(session_data.get("end_time")),
                        last_message_preview=session_data.get("preview_messages", [{}])[0].get("content", ""),
                        topics=session_data.get("topics", []),
                        file_id=self._generate_file_id(session_data.get("session_id", "")),
                        working_directory=session_data.get("working_directory", "unknown"),
                        git_branch=session_data.get("git_branch", "unknown"),
                        duration=session_data.get("duration"),
                        size_bytes=session_data.get("size_bytes", 0),
                        preview_messages=session_data.get("preview_messages", [])
                    )
                    conversations.append(metadata)
                    
                except Exception as e:
                    self.logger.warning(f"Failed to process session: {e}")
                    continue

        except Exception as e:
            self.logger.error(f"Failed to discover conversations: {e}")

        return conversations

    async def _show_conversation_menu(self) -> CommandResult:
        """Show interactive conversation selection menu.

        Returns:
            Command result with modal UI.
        """
        try:
            conversations = await self.discover_conversations()
            
            if not conversations:
                return CommandResult(
                    success=False,
                    message="No saved conversations found.\n\nTip: Use /save to save current conversations for future resumption.",
                    display_type="info"
                )
            
            # Build modal definition
            modal_definition = self._build_conversation_modal(conversations)
            
            return CommandResult(
                success=True,
                message="Select a conversation to resume",
                ui_config=UIConfig(
                    type="modal",
                    title=modal_definition["title"],
                    width=modal_definition.get("width"),
                    height=modal_definition.get("height"),
                    modal_config=modal_definition
                ),
                display_type="modal"
            )

        except Exception as e:
            self.logger.error(f"Error showing conversation menu: {e}")
            return CommandResult(
                success=False,
                message=f"Error loading conversations: {str(e)}",
                display_type="error"
            )

    async def _search_conversations(self, query: str) -> CommandResult:
        """Search conversations by content.

        Args:
            query: Search query

        Returns:
            Command result with search modal.
        """
        try:
            if not self.conversation_logger:
                return CommandResult(
                    success=False,
                    message="Conversation search not available",
                    display_type="error"
                )
            
            sessions = self.conversation_logger.search_sessions(query)
            
            if not sessions:
                return CommandResult(
                    success=False,
                    message=f"No conversations found matching: {query}",
                    display_type="info"
                )
            
            # Convert to conversation metadata
            conversations = []
            for session_data in sessions[:20]:  # Limit search results
                # Strip 'session_' prefix if present for compatibility with conversation_manager
                raw_session_id = session_data.get("session_id", "")
                session_id = raw_session_id.replace("session_", "") if raw_session_id.startswith("session_") else raw_session_id

                metadata = ConversationMetadata(
                    file_path=session_data.get("file_path", ""),
                    session_id=session_id,
                    title=self._generate_session_title(session_data),
                    message_count=session_data.get("message_count", 0),
                    created_time=self._parse_datetime(session_data.get("start_time")),
                    modified_time=self._parse_datetime(session_data.get("end_time")),
                    last_message_preview=session_data.get("preview_messages", [{}])[0].get("content", ""),
                    topics=session_data.get("topics", []),
                    file_id=self._generate_file_id(session_data.get("session_id", "")),
                    working_directory=session_data.get("working_directory", "unknown"),
                    git_branch=session_data.get("git_branch", "unknown"),
                    duration=session_data.get("duration"),
                    size_bytes=session_data.get("size_bytes", 0),
                    preview_messages=session_data.get("preview_messages", []),
                    search_relevance=session_data.get("search_relevance")
                )
                conversations.append(metadata)
            
            # Build search modal
            modal_definition = self._build_search_modal(conversations, query)
            
            return CommandResult(
                success=True,
                message=f"Found {len(conversations)} conversations matching: {query}",
                ui_config=UIConfig(
                    type="modal",
                    title=modal_definition["title"],
                    width=modal_definition.get("width"),
                    height=modal_definition.get("height"),
                    modal_config=modal_definition
                ),
                display_type="modal"
            )

        except Exception as e:
            self.logger.error(f"Error searching conversations: {e}")
            return CommandResult(
                success=False,
                message=f"Error searching conversations: {str(e)}",
                display_type="error"
            )

    def _get_conversation_manager(self):
        """Get or create conversation manager instance.

        Returns:
            Conversation manager instance or None.
        """
        # Return existing if available
        if self.conversation_manager:
            return self.conversation_manager

        # Try to create one
        try:
            from core.llm.conversation_manager import ConversationManager
            from core.utils.config_utils import get_conversations_dir

            # Use a basic config if no manager available
            class BasicConfig:
                def get(self, key, default=None):
                    return default

            config = BasicConfig()
            conversations_dir = get_conversations_dir()
            conversations_dir.mkdir(parents=True, exist_ok=True)

            self.conversation_manager = ConversationManager(config)
            return self.conversation_manager
        except Exception as e:
            self.logger.warning(f"Could not create conversation manager: {e}")
            return None

    def _ensure_conversation_manager(self) -> bool:
        """Ensure conversation manager is available. Returns True if available."""
        if not self.conversation_manager:
            self.conversation_manager = self._get_conversation_manager()
        return self.conversation_manager is not None

    def _prepare_session_display(self, header: str, success_msg: str) -> list:
        """Prepare session messages for display. Loads into llm_service but returns messages instead of displaying.

        Args:
            header: Header message
            success_msg: Success message

        Returns:
            List of display message tuples, or empty list on failure
        """
        if not self.llm_service:
            self.logger.warning("llm_service not available")
            return []

        raw_messages = self.conversation_manager.messages
        self.logger.info(f"[SESSION] raw_messages count: {len(raw_messages)}")

        from core.models import ConversationMessage

        loaded_messages = []
        display_messages = [("system", header, {})]

        for msg in raw_messages:
            role = msg.get("role", "user")
            content = msg.get("content", "")
            loaded_messages.append(ConversationMessage(role=role, content=content))

            if role in ("user", "assistant"):
                display_messages.append((role, content, {}))

        self.llm_service.conversation_history = loaded_messages

        if hasattr(self.llm_service, 'session_stats'):
            self.llm_service.session_stats["messages"] = len(loaded_messages)

        display_messages.append(("system", success_msg, {}))
        return display_messages

    async def _load_and_display_session(self, header: str, success_msg: str) -> CommandResult:
        """Load session into llm_service and display in UI.

        Reads messages from self.conversation_manager.messages (must be populated first).
        Used by both resume and branch after they load/create the session.

        Args:
            header: Header message for the display
            success_msg: Success message to show at end

        Returns:
            CommandResult (always success with empty message, or error)
        """
        if not self.llm_service:
            return CommandResult(success=False, message="LLM service not available", display_type="error")

        raw_messages = self.conversation_manager.messages
        self.logger.info(f"[SESSION] raw_messages count: {len(raw_messages)}")

        from core.models import ConversationMessage

        loaded_messages = []
        messages_for_display = [{"role": "system", "content": header}]

        for msg in raw_messages:
            role = msg.get("role", "user")
            content = msg.get("content", "")
            loaded_messages.append(ConversationMessage(role=role, content=content))

            if role in ("user", "assistant"):
                messages_for_display.append({"role": role, "content": content})

        self.llm_service.conversation_history = loaded_messages

        if hasattr(self.llm_service, 'session_stats'):
            self.llm_service.session_stats["messages"] = len(loaded_messages)

        # Add success message
        messages_for_display.append({"role": "system", "content": success_msg})

        # Use ADD_MESSAGE event for unified display with loading
        from core.events.models import EventType
        await self.event_bus.emit_with_hooks(
            EventType.ADD_MESSAGE,
            {
                "messages": messages_for_display,
                "options": {
                    "show_loading": True,
                    "loading_message": "Loading conversation...",
                    "log_messages": False,  # Already logged
                    "add_to_history": False,  # Already loaded above
                    "display_messages": True
                }
            },
            "resume_plugin"
        )

        return CommandResult(success=True, message="", display_type="success")

    async def _load_conversation(self, session_id: str, force: bool = False) -> CommandResult:
        """Load specific conversation by session ID into a new session."""
        try:
            if not self._ensure_conversation_manager():
                return CommandResult(success=False, message="Conversation manager not available", display_type="error")

            # Auto-save current conversation if it has messages
            if self.conversation_manager.messages:
                old_session = self.conversation_manager.current_session_id
                self.conversation_manager.save_conversation()
                self.logger.info(f"Auto-saved current session: {old_session}")

            # Load the selected conversation's data
            if not self.conversation_manager.load_session(session_id):
                return CommandResult(success=False, message=f"Failed to load session: {session_id}", display_type="error")

            # Create fresh session name for the resumed conversation
            from core.utils.session_naming import generate_session_name
            new_session_id = generate_session_name()
            self.conversation_manager.current_session_id = new_session_id

            return await self._load_and_display_session(
                header=f"--- Resumed: {session_id[:20]}... as {new_session_id} ---",
                success_msg=f"[ok] Resumed: {new_session_id}. Continue below."
            )

        except Exception as e:
            self.logger.error(f"Error loading conversation: {e}")
            return CommandResult(success=False, message=f"Error: {str(e)}", display_type="error")

    async def _handle_resume_options(self, args: List[str]) -> CommandResult:
        """Handle additional resume options and filters.

        Args:
            args: Command arguments

        Returns:
            Command result.
        """
        # Parse filters like --today, --week, --limit N
        filters = {}
        limit = 20
        
        i = 0
        while i < len(args):
            arg = args[i]
            
            if arg == "--today":
                from datetime import date
                filters["date"] = date.today().isoformat()
            elif arg == "--week":
                from datetime import date, timedelta
                filters["date_range"] = (
                    (date.today() - timedelta(days=7)).isoformat(),
                    date.today().isoformat()
                )
            elif arg == "--limit" and i + 1 < len(args):
                try:
                    limit = int(args[i + 1])
                    i += 1
                except ValueError:
                    pass
            elif arg.startswith("--"):
                return CommandResult(
                    success=False,
                    message=f"Unknown option: {arg}",
                    display_type="error"
                )
            
            i += 1
        
        # Apply filters
        conversations = await self.discover_conversations(limit)
        
        # Filter conversations based on criteria
        filtered_conversations = []
        for conv in conversations:
            include = True
            
            if "date" in filters:
                if conv.created_time and conv.created_time.date().isoformat() != filters["date"]:
                    include = False
            
            if "date_range" in filters:
                start_date, end_date = filters["date_range"]
                if conv.created_time:
                    conv_date = conv.created_time.date().isoformat()
                    if not (start_date <= conv_date <= end_date):
                        include = False
            
            if include:
                filtered_conversations.append(conv)
        
        if not filtered_conversations:
            return CommandResult(
                success=False,
                message="No conversations found matching the specified criteria",
                display_type="info"
            )
        
        # Build filtered modal
        modal_definition = self._build_filtered_modal(filtered_conversations, filters)
        
        return CommandResult(
            success=True,
            message=f"Showing {len(filtered_conversations)} filtered conversations",
            ui_config=UIConfig(
                type="modal",
                title=modal_definition["title"],
                width=modal_definition["width"],
                height=modal_definition["height"],
                modal_config=modal_definition
            ),
            display_type="modal"
        )

    def _build_conversation_modal(self, conversations: List[ConversationMetadata]) -> Dict[str, Any]:
        """Build conversation selection modal definition.

        Args:
            conversations: List of conversations

        Returns:
            Modal definition dictionary.
        """
        session_items = []
        for conv in conversations:
            # Format time for display
            time_str = "Unknown"
            if conv.created_time:
                time_str = conv.created_time.strftime("%m/%d %H:%M")

            # Extract short project name from working directory
            project_name = conv.working_directory.split("/")[-1] if conv.working_directory else "unknown"

            # Create preview
            preview = conv.last_message_preview[:80]
            if len(conv.last_message_preview) > 80:
                preview += "..."

            # Get user's actual request (skip system prompt if it's first)
            user_request = ""
            if conv.preview_messages:
                for msg in conv.preview_messages:
                    role = msg.get("role", "")
                    content = msg.get("content", "")
                    # Skip system messages - look for first user message
                    if role == "system":
                        continue
                    if role == "user" and content:
                        user_request = content
                        break

            first_line = user_request.split('\n')[0][:50] if user_request else "Empty"
            if user_request and len(user_request.split('\n')[0]) > 50:
                first_line += "..."

            # Format: [12/11 14:30] "first line of request"
            session_items.append({
                "id": conv.session_id,
                "title": f"[{time_str}] {first_line}",
                "subtitle": f"{conv.message_count} msgs | {conv.duration or '?'} | {project_name} | {conv.git_branch or '-'}",
                "preview": preview,
                "action": "resume_session",
                "exit_mode": "minimal",  # Plugin will display content after modal exit
                "metadata": {
                    "session_id": conv.session_id,
                    "file_id": conv.file_id,
                    "working_directory": conv.working_directory,
                    "git_branch": conv.git_branch,
                    "topics": conv.topics
                }
            })
        
        return {
            "title": "Resume Conversation",
            "footer": "↑↓ navigate • Enter select • Tab search • F filter • Esc exit",
            # Width is dynamic (terminal_width - 2)
            "height": 20,
            "sections": [
                {
                    "title": f"Recent Conversations ({len(conversations)} available)",
                    "type": "session_list",
                    "sessions": session_items
                }
            ],
            "actions": [
                {"key": "Enter", "label": "Resume", "action": "select"},
                {"key": "Tab", "label": "Search", "action": "search"},
                {"key": "F", "label": "Filter", "action": "filter"},
                {"key": "Escape", "label": "Cancel", "action": "cancel"}
            ]
        }

    def _build_search_modal(self, conversations: List[ConversationMetadata], query: str) -> Dict[str, Any]:
        """Build search results modal definition.

        Args:
            conversations: Search results
            query: Search query

        Returns:
            Modal definition dictionary.
        """
        session_items = []
        for conv in conversations:
            # Format time for display
            time_str = "Unknown"
            if conv.created_time:
                time_str = conv.created_time.strftime("%m/%d %H:%M")

            # Extract short project name
            project_name = conv.working_directory.split("/")[-1] if conv.working_directory else "unknown"

            # Get user's actual request (skip system prompt if it's first)
            user_request = ""
            if conv.preview_messages:
                for msg in conv.preview_messages:
                    role = msg.get("role", "")
                    content = msg.get("content", "")
                    # Skip system messages - look for first user message
                    if role == "system":
                        continue
                    if role == "user" and content:
                        user_request = content
                        break

            first_line = user_request.split('\n')[0][:40] if user_request else "Empty"
            if user_request and len(user_request.split('\n')[0]) > 40:
                first_line += "..."

            # Relevance score if available
            relevance_text = f" [{conv.search_relevance:.0%}]" if conv.search_relevance else ""

            session_items.append({
                "id": conv.session_id,
                "title": f"[{time_str}] {first_line}{relevance_text}",
                "subtitle": f"{conv.message_count} msgs | {conv.duration or '?'} | {project_name} | {conv.git_branch or '-'}",
                "preview": conv.last_message_preview[:80],
                "metadata": {
                    "session_id": conv.session_id,
                    "file_id": conv.file_id,
                    "search_relevance": conv.search_relevance
                }
            })
        
        return {
            "title": f"Search Results: {query}",
            "footer": "↑↓ navigate • Enter select • Esc back",
            # Width is dynamic (terminal_width - 2)
            "height": 20,
            "sections": [
                {
                    "title": f"Found {len(conversations)} conversations",
                    "type": "session_list",
                    "sessions": session_items
                }
            ],
            "actions": [
                {"key": "Enter", "label": "Resume", "action": "select"},
                {"key": "Escape", "label": "Back", "action": "cancel"}
            ]
        }

    def _build_filtered_modal(self, conversations: List[ConversationMetadata], filters: Dict) -> Dict[str, Any]:
        """Build filtered results modal definition.

        Args:
            conversations: Filtered conversations
            filters: Applied filters

        Returns:
            Modal definition dictionary.
        """
        filter_desc = []
        if "date" in filters:
            filter_desc.append(f"Date: {filters['date']}")
        if "date_range" in filters:
            start, end = filters["date_range"]
            filter_desc.append(f"Date: {start} to {end}")
        
        filter_text = " • ".join(filter_desc) if filter_desc else "Filtered"
        
        session_items = []
        for conv in conversations:
            # Format time for display
            time_str = "Unknown"
            if conv.created_time:
                time_str = conv.created_time.strftime("%m/%d %H:%M")

            # Extract short project name
            project_name = conv.working_directory.split("/")[-1] if conv.working_directory else "unknown"

            # Get user's actual request (skip system prompt if it's first)
            user_request = ""
            if conv.preview_messages:
                for msg in conv.preview_messages:
                    role = msg.get("role", "")
                    content = msg.get("content", "")
                    # Skip system messages - look for first user message
                    if role == "system":
                        continue
                    if role == "user" and content:
                        user_request = content
                        break

            first_line = user_request.split('\n')[0][:50] if user_request else "Empty"
            if user_request and len(user_request.split('\n')[0]) > 50:
                first_line += "..."

            session_items.append({
                "id": conv.session_id,
                "title": f"[{time_str}] {first_line}",
                "subtitle": f"{conv.message_count} msgs | {conv.duration or '?'} | {project_name} | {conv.git_branch or '-'}",
                "preview": conv.last_message_preview[:80],
                "metadata": {
                    "session_id": conv.session_id,
                    "file_id": conv.file_id
                }
            })
        
        return {
            "title": f"Filtered Conversations ({filter_text})",
            "footer": "↑↓ navigate • Enter select • Esc back",
            # Width is dynamic (terminal_width - 2)
            "height": 20,
            "sections": [
                {
                    "title": f"Showing {len(conversations)} conversations",
                    "type": "session_list",
                    "sessions": session_items
                }
            ],
            "actions": [
                {"key": "Enter", "label": "Resume", "action": "select"},
                {"key": "Escape", "label": "Back", "action": "cancel"}
            ]
        }

    def _generate_session_title(self, session_data: Dict) -> str:
        """Generate a descriptive title for a session.

        Args:
            session_data: Session data

        Returns:
            Generated title
        """
        topics = session_data.get("topics", [])
        working_dir = session_data.get("working_directory", "unknown")
        
        # Extract project name from working directory
        project_name = working_dir.split("/")[-1] if working_dir != "unknown" else "Unknown Project"
        
        # Use topic if available, otherwise use generic title
        if topics:
            main_topic = topics[0].replace("_", " ").title()
            return f"{main_topic} - {project_name}"
        else:
            return f"Conversation - {project_name}"

    def _generate_file_id(self, session_id: str) -> str:
        """Generate short file ID for display.

        Args:
            session_id: Full session ID

        Returns:
            Short file ID
        """
        # Simple hash to generate a consistent short ID
        hash_val = hash(session_id) % 100000
        return f"#{hash_val:05d}"

    def _parse_datetime(self, dt_str: Optional[str]) -> Optional[datetime]:
        """Parse datetime string.

        Args:
            dt_str: Datetime string

        Returns:
            Parsed datetime or None
        """
        if not dt_str:
            return None
        
        try:
            from datetime import datetime
            # Handle ISO format with Z
            if dt_str.endswith('Z'):
                dt_str = dt_str.replace('Z', '+00:00')
            return datetime.fromisoformat(dt_str)
        except:
            return None

    async def shutdown(self) -> None:
        """Shutdown the plugin and cleanup resources."""
        try:
            self.logger.info("Resume conversation plugin shutdown completed")
        except Exception as e:
            self.logger.error(f"Error shutting down resume conversation plugin: {e}")

    @staticmethod
    def get_default_config() -> Dict[str, Any]:
        """Get default configuration for resume conversation plugin.

        Returns:
            Default configuration dictionary.
        """
        return {
            "plugins": {
                "resume_conversation": {
                    "enabled": True,
                    "max_conversations": 50,
                    "preview_length": 80,
                    "auto_save_current": True,
                    "confirm_load": True,
                    "session_retention_days": 30
                }
            }
        }

    async def register_hooks(self) -> None:
        """Register event hooks for the plugin."""
        from core.events.models import EventType, Hook
        hook = Hook(
            name="resume_modal_command",
            plugin_name="resume_conversation",
            event_type=EventType.MODAL_COMMAND_SELECTED,
            priority=10,
            callback=self._handle_modal_command
        )
        await self.event_bus.register_hook(hook)

    async def _handle_modal_command(self, data: Dict[str, Any], event: Event) -> Dict[str, Any]:
        """Handle modal command selection events.

        Args:
            data: Event data containing command info.
            event: Event object.

        Returns:
            Modified data dict with display_messages or show_modal keys.
        """
        command = data.get("command", {})
        action = command.get("action")

        if action == "resume_session":
            session_id = command.get("session_id") or command.get("metadata", {}).get("session_id")
            if session_id:
                self.logger.info(f"[RESUME] Modal selected session: {session_id}")

                if self._ensure_conversation_manager() and self.conversation_manager.load_session(session_id):
                    # Load messages into llm_service history
                    display_messages = self._prepare_session_display(
                        header=f"--- Resumed session: {session_id} ---",
                        success_msg=f"[ok] Resumed: {session_id}. Continue below."
                    )

                    if display_messages:
                        # Convert display tuples to ADD_MESSAGE format
                        messages = [
                            {"role": role, "content": content}
                            for role, content, _ in display_messages
                        ]

                        # Use ADD_MESSAGE event for unified display with loading
                        from core.events.models import EventType
                        await self.event_bus.emit_with_hooks(
                            EventType.ADD_MESSAGE,
                            {
                                "messages": messages,
                                "options": {
                                    "show_loading": True,
                                    "loading_message": "Loading conversation...",
                                    "log_messages": False,  # Already logged
                                    "add_to_history": False,  # Already loaded by _prepare_session_display
                                    "display_messages": True
                                }
                            },
                            "resume_plugin"
                        )

        elif action == "branch_select_session":
            session_id = command.get("session_id") or command.get("metadata", {}).get("session_id")
            if session_id:
                self.logger.info(f"[BRANCH] Modal selected session for branch: {session_id}")
                result = await self._show_branch_point_selector(session_id)
                if result and result.ui_config and result.display_type == "modal":
                    data["show_modal"] = result.ui_config.modal_config

        elif action == "search":
            # Show search options modal
            self.logger.info("[RESUME] Search action triggered")
            data["show_modal"] = {
                "title": "Search Conversations",
                "footer": "Enter select • Esc back",
                # Width is dynamic (terminal_width - 2)
                "height": 12,
                "sections": [
                    {
                        "title": "Search by command",
                        "commands": [
                            {"name": "/resume search <query>", "description": "Search conversation content"},
                            {"name": "/resume search git", "description": "Example: find git-related chats"},
                            {"name": "/resume search modal", "description": "Example: find modal discussions"},
                        ]
                    }
                ]
            }

        elif action == "filter":
            # Show filter options modal
            self.logger.info("[RESUME] Filter action triggered")
            data["show_modal"] = {
                "title": "Filter Conversations",
                "footer": "Enter select • Esc back",
                # Width is dynamic (terminal_width - 2)
                "height": 14,
                "sections": [
                    {
                        "title": "Filter options",
                        "commands": [
                            {"name": "Today's conversations", "description": "Show only today", "action": "filter_today"},
                            {"name": "This week", "description": "Show this week's conversations", "action": "filter_week"},
                            {"name": "Show more", "description": "Show up to 50 conversations", "action": "filter_limit"},
                        ]
                    }
                ]
            }

        elif action == "filter_today":
            self.logger.info("[RESUME] Filter today triggered")
            result = await self._handle_resume_options(["--today"])
            if result and result.ui_config and result.display_type == "modal":
                data["show_modal"] = result.ui_config.modal_config

        elif action == "filter_week":
            self.logger.info("[RESUME] Filter week triggered")
            result = await self._handle_resume_options(["--week"])
            if result and result.ui_config and result.display_type == "modal":
                data["show_modal"] = result.ui_config.modal_config

        elif action == "filter_limit":
            self.logger.info("[RESUME] Filter limit triggered")
            result = await self._handle_resume_options(["--limit", "50"])
            if result and result.ui_config and result.display_type == "modal":
                data["show_modal"] = result.ui_config.modal_config

        elif action == "branch_execute":
            metadata = command.get("metadata", {})
            session_id = metadata.get("session_id")
            message_index = metadata.get("message_index")
            if session_id is not None and message_index is not None:
                self.logger.info(f"[BRANCH] Executing branch: {session_id} at {message_index}")
                if self._ensure_conversation_manager():
                    result = self.conversation_manager.branch_session(session_id, message_index)
                    if result.get("success"):
                        new_session_id = result.get("session_id")
                        display_messages = self._prepare_session_display(
                            header=f"--- Branched from {session_id} at message {message_index} ---",
                            success_msg=(
                                f"[ok] Created branch: {new_session_id}\n"
                                f"    From: {session_id} at message {result['branch_point']}\n"
                                f"    Loaded {result['message_count']} messages. Continue below."
                            )
                        )
                        if display_messages:
                            # Convert display tuples to ADD_MESSAGE format
                            messages = [
                                {"role": role, "content": content}
                                for role, content, _ in display_messages
                            ]

                            # Use ADD_MESSAGE event for unified display with loading
                            from core.events.models import EventType
                            await self.event_bus.emit_with_hooks(
                                EventType.ADD_MESSAGE,
                                {
                                    "messages": messages,
                                    "options": {
                                        "show_loading": True,
                                        "loading_message": "Creating branch...",
                                        "log_messages": False,  # Already logged
                                        "add_to_history": False,  # Already loaded by _prepare_session_display
                                        "display_messages": True
                                    }
                                },
                                "resume_plugin"
                            )

        return data
