"""
CLI Interface module for OpenQube.

This module handles all user interaction, input collection, and output formatting.
"""

from typing import List, Optional
import sys
import inquirer
from colorama import Fore, Style, init
import time
import threading
import re
from prompt_toolkit import prompt
from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.styles import Style as PromptStyle
from rich.console import Console
from rich.panel import Panel
from rich.markdown import Markdown
from rich.syntax import Syntax

init(autoreset=True)

console = Console()
WIDTH = 80  # Increased width for better readability


class CommandCompleter(Completer):
    """Autocomplete completer for slash commands."""
    
    def __init__(self):
        self.commands = {
            "/models": "Switch model",
            "/providers": "Switch provider",
            "/clear": "Clear conversation",
            "/skills": "List agent skills",
            "/tools": "List available tools",
            "/exit": "Exit application",
            "/help": "Show help"
        }
    
    def get_completions(self, document, complete_event):
        text = document.text_before_cursor
        
        # Only show completions if text starts with /
        if text.startswith('/'):
            for cmd, desc in self.commands.items():
                if cmd.startswith(text.lower()):
                    yield Completion(
                        cmd,
                        start_position=-len(text),
                        display=f"{cmd}",
                        display_meta=desc
                    )


def get_command_match(text: str) -> Optional[str]:
    """Get the first matching command for auto-completion."""
    commands = ["/models", "/providers", "/clear", "/skills", "/tools", "/exit", "/help"]
    
    if text.startswith('/') and len(text) > 1:
        for cmd in commands:
            if cmd.startswith(text.lower()):
                return cmd
    return None


def separator():
    return f"{Fore.CYAN}{'─' * WIDTH}{Style.RESET_ALL}"


def display_branding() -> None:
    from src import __version__

    # Box width (interior space)
    box_width = 80
    
    # ASCII art logo lines (without color codes)
    logo_lines = [
        " ███████╗███████╗███████╗██████╗ ",
        " ╚══███╔╝██╔════╝██╔════╝██╔══██╗",
        "   ███╔╝ █████╗  █████╗  ██████╔╝",
        "  ███╔╝  ██╔══╝  ██╔══╝  ██╔══██╗",
        " ███████╗███████╗███████╗██║  ██║",
        " ╚══════╝╚══════╝╚══════╝╚═╝  ╚═╝"
    ]
    
    # Calculate centered logo
    logo_width = len(logo_lines[0])
    logo_padding = (box_width - logo_width) // 2
    
    # Text lines
    version_text = f"Zeer v{__version__}"
    subtitle_text = "Agentic AI CLI"
    
    # Calculate centered text
    version_padding = (box_width - len(version_text)) // 2
    subtitle_padding = (box_width - len(subtitle_text)) // 2
    
    # Build banner with gradient effect
    lines = []
    lines.append(f"{Fore.CYAN}╔{'═' * box_width}╗")
    lines.append(f"║{' ' * box_width}║")
    
    # Add logo lines
    for logo_line in logo_lines:
        padding_left = ' ' * logo_padding
        padding_right = ' ' * (box_width - logo_padding - logo_width)
        lines.append(f"║{padding_left}{Fore.MAGENTA}{logo_line}{Fore.CYAN}{padding_right}║")
    
    lines.append(f"║{' ' * box_width}║")
    
    # Add version line
    padding_left = ' ' * version_padding
    padding_right = ' ' * (box_width - version_padding - len(version_text))
    lines.append(f"║{padding_left}{Fore.WHITE}{version_text}{Fore.CYAN}{padding_right}║")
    
    # Add subtitle line
    padding_left = ' ' * subtitle_padding
    padding_right = ' ' * (box_width - subtitle_padding - len(subtitle_text))
    lines.append(f"║{padding_left}{Fore.GREEN}{subtitle_text}{Fore.CYAN}{padding_right}║")
    
    lines.append(f"║{' ' * box_width}║")
    lines.append(f"╚{'═' * box_width}╝{Style.RESET_ALL}")
    
    banner = '\n' + '\n'.join(lines) + '\n'
    print(banner)


def display_error(error: str) -> None:
    print(f"\n{Fore.RED}✗ Error:{Style.RESET_ALL} {error}\n", file=sys.stderr)


def prompt_choice(prompt: str, options: List[str]) -> str:
    questions = [
        inquirer.List(
            "choice",
            message=prompt,
            choices=options,
            carousel=True,
        ),
    ]

    answers = inquirer.prompt(questions)
    if answers is None:
        raise KeyboardInterrupt

    return answers["choice"]


def prompt_slash_command() -> str:
    commands = [
        "/models - Switch model",
        "/providers - Switch provider",
        "/clear - Clear conversation",
        "/skills - List agent skills",
        "/tools - List available tools",
        "/exit - Exit application",
        "/help - Show help",
        "Cancel",
    ]

    try:
        questions = [
            inquirer.List(
                "command",
                message="Select command",
                choices=commands,
                carousel=True,
            )
        ]

        answers = inquirer.prompt(questions)

        if answers is None or answers["command"] == "Cancel":
            return ""

        return answers["command"].split(" - ")[0]

    except KeyboardInterrupt:
        return ""


def display_success(message: str) -> None:
    print(f"{Fore.GREEN}✓{Style.RESET_ALL} {message}")


def display_info(message: str) -> None:
    print(f"{Fore.CYAN}ℹ{Style.RESET_ALL} {message}")


def display_separator() -> None:
    print("\n" + separator() + "\n")


def clear_screen() -> None:
    """Clear the terminal screen."""
    import os
    os.system('cls' if os.name == 'nt' else 'clear')


def display_input_prompt_with_slash_detection() -> tuple:
    """
    Advanced input with fixed position and autocomplete.
    """
    from prompt_toolkit.formatted_text import HTML
    
    # Print separators BEFORE input
    print()  # Add spacing
    console.print(f"[dim]{'─' * WIDTH}[/dim]")
    
    # Custom style for prompt - using class names
    prompt_style = PromptStyle.from_dict({
        'prompt': 'cyan',
        'placeholder': 'ansibrightblack',  # Grey placeholder
    })
    
    try:
        # Get input with autocomplete and placeholder
        user_input = prompt(
            '> ',
            completer=CommandCompleter(),
            complete_while_typing=True,
            style=prompt_style,
            placeholder=HTML('<style color="#808080">Type your message here...</style>'),
            bottom_toolbar='Press / for commands'
        ).strip()
        
        # Auto-complete if it's a partial command match
        if user_input.startswith('/') and user_input not in ["/models", "/providers", "/clear", "/skills", "/tools", "/exit", "/help"]:
            match = get_command_match(user_input)
            if match:
                user_input = match
        
        # Print bottom separator after input
        console.print(f"[dim]{'─' * WIDTH}[/dim]\n")
        
        # Check if user typed just "/" - show menu
        if user_input == "/":
            command = prompt_slash_command()
            return command, True
        
        return user_input, False
        
    except (KeyboardInterrupt, EOFError):
        print()
        return "", False


def display_input_prompt() -> str:
    sep = separator()

    print("\n" + sep)
    user_input = input(f"{Fore.YELLOW}>{Style.RESET_ALL} ").strip()
    print(sep + "\n")

    return user_input


def display_user_message(message: str) -> None:
    """Display user message - intentionally empty as we don't show user messages."""
    pass  # Don't display user messages


def display_assistant_message(
    message: str,
    model: str,
    tokens: Optional[dict] = None,
    elapsed_time: float = 0,
    context_window: Optional[int] = None,
) -> None:
    """Display assistant message with rich formatting."""
    
    # Use rich to render markdown
    md = Markdown(message)
    console.print(md)
    console.print()
    
    # Build metadata line - all grey
    metadata_parts = []
    metadata_parts.append(f"{model}")
    metadata_parts.append(f"{elapsed_time:.1f}s")
    
    if tokens:
        # Show output/completion tokens
        completion_tokens = tokens.get('completionTokens', 0)
        if completion_tokens > 0:
            metadata_parts.append(f"{completion_tokens:,} tokens")
        
        # Display context usage percentage
        prompt_tokens = tokens.get('promptTokens', 0)
        if context_window and context_window > 0:
            context_pct = (prompt_tokens / context_window) * 100
            metadata_parts.append(f"{context_pct:.1f}% context")
        elif prompt_tokens > 0:
            # Show token count if no context window available
            metadata_parts.append(f"{prompt_tokens:,} context tokens")
    
    console.print(f"[dim]{' • '.join(metadata_parts)}[/dim]")
    console.print(f"[dim]{'─' * WIDTH}[/dim]\n")


def format_message_with_code_blocks(message: str) -> str:
    """Format message with syntax highlighting for code blocks and bold text."""
    # First handle code blocks
    parts = re.split(r'(```[\s\S]*?```|`[^`]+`)', message)
    
    formatted_parts = []
    for part in parts:
        if part.startswith('```') and part.endswith('```'):
            # Multi-line code block
            lines = part[3:-3].split('\n')
            lang = lines[0].strip() if lines else ''
            code = '\n'.join(lines[1:]) if len(lines) > 1 else lines[0]
            
            formatted_parts.append(f"\n{Fore.LIGHTBLACK_EX}┌─ {lang if lang else 'code'} ─{Style.RESET_ALL}")
            for line in code.split('\n'):
                formatted_parts.append(f"{Fore.LIGHTBLACK_EX}│{Style.RESET_ALL} {Fore.WHITE}{line}{Style.RESET_ALL}")
            formatted_parts.append(f"{Fore.LIGHTBLACK_EX}└{'─' * (WIDTH - 2)}{Style.RESET_ALL}\n")
        elif part.startswith('`') and part.endswith('`'):
            # Inline code
            code = part[1:-1]
            formatted_parts.append(f"{Fore.YELLOW}{code}{Style.RESET_ALL}")
        else:
            # Handle bold text (**text**)
            part = re.sub(r'\*\*([^*]+)\*\*', f'{Style.BRIGHT}\\1{Style.NORMAL}', part)
            # Regular text
            formatted_parts.append(part)
    
    return ''.join(formatted_parts)


class RunningIndicator:
    """Display running indicator with animated spinner and elapsed time."""

    def __init__(self):
        self.running = False
        self.thread = None
        self.start_time = 0
        self.spinner_chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
        self.spinner_idx = 0

    def start(self):
        self.running = True
        self.start_time = time.time()
        self.thread = threading.Thread(target=self._display)
        self.thread.daemon = True
        self.thread.start()

    def stop(self) -> float:
        self.running = False
        if self.thread:
            self.thread.join(timeout=0.5)

        elapsed = time.time() - self.start_time
        print("\r" + " " * WIDTH + "\r", end="", flush=True)
        return elapsed

    def _display(self):
        while self.running:
            elapsed = int(time.time() - self.start_time)
            spinner = self.spinner_chars[self.spinner_idx % len(self.spinner_chars)]
            self.spinner_idx += 1
            
            print(
                f"\r{Fore.CYAN}{spinner}{Style.RESET_ALL} {Fore.LIGHTBLACK_EX}Thinking... {elapsed}s{Style.RESET_ALL}",
                end="",
                flush=True,
            )
            time.sleep(0.1)