"""
Command Menu - Display available commands like Claude Code's "/" menu.

Shows a formatted list of available commands when the user types "/".
"""

from dataclasses import dataclass
from typing import List, Optional

from .colors import Formatter as fmt, Theme, style, Color


@dataclass
class Command:
    """Represents a CLI command."""
    name: str
    args: str
    description: str
    category: str


# All available orchestrator commands
COMMANDS = [
    # Project Management
    Command("/project", "new <task>", "Plan and create a new project", "Projects"),
    Command("/project", "list", "List recent projects", "Projects"),
    Command("/project", "resume <id>", "Resume a previous project", "Projects"),
    Command("/project", "status", "Show current project status", "Projects"),
    Command("/project", "archive <id>", "Archive a completed project", "Projects"),

    # Agent Templates
    Command("/agent", "list", "List available agent templates", "Agents"),
    Command("/agent", "create", "Create a custom agent template", "Agents"),
    Command("/agent", "info <id>", "Show agent template details", "Agents"),
    Command("/agent", "export <id>", "Export template to YAML", "Agents"),
    Command("/agent", "import <file>", "Import template from YAML", "Agents"),

    # Task Management
    Command("/assign", "<agent> <task>", "Assign a task to a specific agent", "Task Management"),
    Command("/cancel", "<task-id>", "Cancel a running or pending task", "Task Management"),
    Command("/broadcast", "<message>", "Send info to all agents", "Task Management"),
    Command("/priority", "<task-id> <level>", "Set task priority (high/medium/low)", "Task Management"),

    # Monitoring
    Command("/status", "[agent-id]", "Show system or agent status", "Monitoring"),
    Command("/progress", "[task-id]", "Show running task progress", "Monitoring"),
    Command("/usage", "", "Show token/session usage for all agents", "Monitoring"),
    Command("/health", "", "Check agent health and availability", "Monitoring"),
    Command("/report", "", "Generate a full status report", "Monitoring"),

    # Memory & Context
    Command("/memory", "search <query>", "Search project memory", "Memory"),
    Command("/memory", "add <type> <content>", "Add to project memory", "Memory"),
    Command("/decisions", "", "Show recent architectural decisions", "Memory"),
    Command("/context", "<task-id>", "Get full context for a task", "Memory"),

    # Agent Operations
    Command("/spawn", "<type> [config]", "Create a specialized agent", "Agent Operations"),
    Command("/view", "<agent-id> [--attach]", "View agent's console session", "Agent Operations"),
    Command("/pause", "<agent-id>", "Pause an agent", "Agent Operations"),
    Command("/resume", "<agent-id>", "Resume a paused agent", "Agent Operations"),
    Command("/reassign", "<task-id> <agent>", "Move task to different agent", "Agent Operations"),

    # System
    Command("/save", "", "Save current state", "System"),
    Command("/help", "", "Show detailed help", "System"),
    Command("/exit", "", "Stop the orchestrator", "System"),
]


class CommandMenu:
    """
    Displays the command menu in a formatted, colored style.
    """

    @staticmethod
    def render(filter_text: Optional[str] = None) -> str:
        """
        Render the command menu.

        Args:
            filter_text: Optional text to filter commands by

        Returns:
            Formatted command menu string
        """
        lines = []

        # Header
        lines.append("")
        lines.append(fmt.header("  Available Commands"))
        lines.append(fmt.divider("─", 60))
        lines.append("")

        # Filter commands if needed
        commands = COMMANDS
        if filter_text:
            filter_lower = filter_text.lower()
            commands = [
                c for c in commands
                if filter_lower in c.name.lower() or filter_lower in c.description.lower()
            ]

        if not commands:
            lines.append(fmt.dim("  No matching commands found"))
            lines.append("")
            return "\n".join(lines)

        # Group by category
        categories = {}
        for cmd in commands:
            if cmd.category not in categories:
                categories[cmd.category] = []
            categories[cmd.category].append(cmd)

        # Render each category
        for category, cmds in categories.items():
            # Category header
            lines.append(f"  {style(category, Theme.SECONDARY, Color.BOLD)}")
            lines.append("")

            for cmd in cmds:
                # Command name in yellow/accent
                name = style(cmd.name, Theme.COMMAND, Color.BOLD)

                # Args in dim
                args = style(cmd.args, Theme.TEXT_DIM) if cmd.args else ""

                # Description
                desc = style(cmd.description, Theme.TEXT)

                # Format the line
                if args:
                    lines.append(f"    {name} {args}")
                else:
                    lines.append(f"    {name}")
                lines.append(f"      {desc}")
                lines.append("")

        # Footer hint
        lines.append(fmt.divider("─", 60))
        hint = style("Type a command or enter a task description", Theme.TEXT_DIM)
        lines.append(f"  {hint}")
        lines.append("")

        return "\n".join(lines)

    @staticmethod
    def render_compact() -> str:
        """
        Render a compact version of the command menu.

        Returns:
            Compact command menu string
        """
        lines = []
        lines.append("")
        lines.append(fmt.header("  Commands"))
        lines.append("")

        # Group by category
        categories = {}
        for cmd in COMMANDS:
            if cmd.category not in categories:
                categories[cmd.category] = []
            categories[cmd.category].append(cmd)

        for category, cmds in categories.items():
            cat_style = style(f"{category}:", Theme.SECONDARY)
            cmd_list = " ".join(style(c.name, Theme.COMMAND) for c in cmds)
            lines.append(f"  {cat_style} {cmd_list}")

        lines.append("")
        lines.append(fmt.dim("  Type /help for detailed command info"))
        lines.append("")

        return "\n".join(lines)

    @staticmethod
    def render_agent_types() -> str:
        """
        Render available agent types for /spawn and /agent.

        Returns:
            Formatted agent types string
        """
        # Try to use the template registry
        try:
            from ..agents.templates import list_templates
            templates = list_templates()

            lines = []
            lines.append("")
            lines.append(fmt.header("  Available Agent Templates"))
            lines.append(fmt.divider("─", 60))
            lines.append("")

            # Group by domain
            domains = {}
            for template in templates:
                domain = template.domain.value.replace("_", " ").title()
                if domain not in domains:
                    domains[domain] = []
                domains[domain].append(template)

            for domain, templates_in_domain in domains.items():
                lines.append(f"  {style(domain, Theme.SECONDARY, Color.BOLD)}")
                lines.append("")
                for template in templates_in_domain:
                    name = style(template.id, Theme.AGENT_NAME)
                    desc = style(template.description[:60], Theme.TEXT_DIM)
                    lines.append(f"    {name}")
                    lines.append(f"      {desc}")
                    lines.append("")

            lines.append(fmt.divider("─", 60))
            lines.append(fmt.dim("  Use /agent info <id> for details"))
            lines.append(fmt.dim("  Use /spawn <id> to create an agent"))
            lines.append("")

            return "\n".join(lines)

        except ImportError:
            # Fallback if templates not available
            agent_types = [
                ("frontend-specialist", "React, Vue, CSS, accessibility, performance"),
                ("backend-specialist", "APIs, databases, authentication, server architecture"),
                ("test-engineer", "Unit tests, integration tests, E2E tests, coverage"),
                ("devops-specialist", "CI/CD, Docker, Kubernetes, infrastructure"),
                ("story-writer", "Fiction, narratives, creative writing"),
                ("editor", "Proofreading, style, clarity"),
                ("researcher", "Information gathering, synthesis"),
            ]

            lines = []
            lines.append("")
            lines.append(fmt.header("  Agent Types"))
            lines.append(fmt.divider("─", 60))
            lines.append("")

            for agent_type, description in agent_types:
                name = style(agent_type, Theme.AGENT_NAME)
                desc = style(description, Theme.TEXT_DIM)
                lines.append(f"    {name}")
                lines.append(f"      {desc}")
                lines.append("")

            lines.append(fmt.dim("  Example: /spawn frontend-specialist"))
            lines.append("")

            return "\n".join(lines)


def show_command_menu(filter_text: Optional[str] = None, compact: bool = False) -> None:
    """
    Print the command menu to stdout.

    Args:
        filter_text: Optional text to filter commands
        compact: Use compact format
    """
    if compact:
        print(CommandMenu.render_compact())
    else:
        print(CommandMenu.render(filter_text))
