"""REPL command parsing and handling functionality."""

import logging
from argparse import Namespace
from typing import Callable, Optional

from prompt_toolkit.formatted_text import HTML

from promptheus.config import Config
from promptheus.constants import VERSION, GITHUB_REPO, GITHUB_ISSUES
from promptheus.providers import LLMProvider, get_provider
from promptheus.utils import sanitize_error_message

logger = logging.getLogger(__name__)

MessageSink = Callable[[str], None]


def create_command_registry():
    """Create a registry of command handlers for extensibility."""
    from .history_view import display_history
    from promptheus.utils import copy_to_clipboard
    from promptheus.history import get_history

    def handle_about(args_list, app_config, args, console, notify):
        show_about(console, app_config)
        return "handled"

    def handle_bug(args_list, app_config, args, console, notify):
        show_bug_report(console)
        return "handled"

    def handle_clear_history(args_list, app_config, args, console, notify):
        import questionary
        try:
            confirm = questionary.confirm(
                "Are you sure you want to clear all history?",
                default=False,
            ).ask()
            if confirm:
                get_history().clear()
                console.print("[green]✓[/green] History cleared")
        except KeyboardInterrupt:
            console.print("[yellow]Cancelled[/yellow]")
        return "handled"

    def handle_copy(args_list, app_config, args, console, notify, last_result=None):
        if last_result:
            copy_to_clipboard(last_result, console, notify)
        else:
            console.print("[yellow]No result to copy yet. Process a prompt first.[/yellow]")
        return "handled"

    def handle_help(args_list, app_config, args, console, notify):
        show_help(console)
        return "handled"

    def handle_history(args_list, app_config, args, console, notify):
        display_history(console, notify)
        return "handled"

    def handle_load(args_list, app_config, args, console, notify):
        if len(args_list) > 0:
            try:
                index = int(args_list[0])
                entry = get_history().get_by_index(index)
                if entry:
                    console.print(f"[green]✓[/green] Loaded prompt #{index} from history:\n")
                    console.print(f"[cyan]{entry.original_prompt}[/cyan]\n")
                    return ("load_prompt", entry.original_prompt)
                else:
                    console.print(f"[yellow]No history entry found at index {index}[/yellow]")
                    return "handled"
            except ValueError:
                console.print("[yellow]Invalid history index. Use '/load <number>'[/yellow]")
                return "handled"
        else:
            console.print("[yellow]Specify which prompt to load. Showing history:[/yellow]\n")
            display_history(console, notify)
            return "handled"

    return {
        'about': handle_about,
        'bug': handle_bug,
        'clear-history': handle_clear_history,
        'copy': handle_copy,
        'help': handle_help,
        'history': handle_history,
        'load': handle_load,
    }


def show_help(console) -> None:
    """Display help information about available commands."""
    console.print()
    console.print("[bold cyan]Session Commands:[/bold cyan]")
    console.print()
    console.print("  [bold]/set model <name>[/bold]     Change model (e.g., /set model gpt-4)")
    console.print("  [bold]/set provider <name>[/bold]  Change AI provider (e.g., /set provider claude)")
    console.print("  [bold]/status[/bold]               Show current session settings")
    console.print("  [bold]/toggle skip-questions[/bold] Toggle skip-questions mode on/off")
    console.print("  [bold]/toggle refine[/bold]        Toggle refine mode on/off")
    console.print()
    console.print("[bold cyan]Other Commands:[/bold cyan]")
    console.print()
    console.print("  [bold]/about[/bold]                Show version info")
    console.print("  [bold]/bug[/bold]                  Submit a bug report")
    console.print("  [bold]/clear-history[/bold]        Clear all history")
    console.print("  [bold]/copy[/bold]                 Copy the last result to clipboard")
    console.print("  [bold]/exit[/bold] or [bold]/quit[/bold]       Exit Promptheus")
    console.print("  [bold]/help[/bold]                 Show this help message")
    console.print("  [bold]/history[/bold]              View recent prompts")
    console.print("  [bold]/load <number>[/bold]        Load a prompt from history")
    console.print()
    console.print("[bold cyan]Key Bindings:[/bold cyan]")
    console.print()
    console.print("  [bold]Enter[/bold]                 Submit your prompt")
    console.print("  [bold]Shift+Enter[/bold]           Add a new line (multiline input)")
    console.print("  [bold]Option/Alt+Enter[/bold]      Alternate shortcut for new line")
    console.print("  [bold]Ctrl+C[/bold]                Cancel input (press twice to exit)")
    console.print("  [bold]Ctrl+D[/bold]                Exit Promptheus")
    console.print()
    console.print("[dim]Tip: Type / then Tab to see all available commands[/dim]")
    console.print()


def show_about(console, app_config: Config) -> None:
    """Display version and system information."""
    import platform
    import sys

    console.print()
    console.print("[bold cyan]Promptheus - AI-powered Prompt Engineering[/bold cyan]")
    console.print()
    console.print(f"  [bold]Version:[/bold]       {VERSION}")
    console.print(f"  [bold]GitHub:[/bold]        {GITHUB_REPO}")
    console.print()
    console.print("[bold cyan]System Information:[/bold cyan]")
    console.print()
    console.print(f"  [bold]Python:[/bold]        {sys.version.split()[0]}")
    console.print(f"  [bold]Platform:[/bold]      {platform.system()} {platform.release()}")
    console.print()
    console.print("[bold cyan]Current Configuration:[/bold cyan]")
    console.print()
    console.print(f"  [bold]Provider:[/bold]      {app_config.provider or 'auto-detect'}")
    console.print(f"  [bold]Model:[/bold]         {app_config.get_model() or 'default'}")

    configured = app_config.get_configured_providers()
    if configured:
        console.print(f"  [bold]Available:[/bold]     {', '.join(configured)}")
    console.print()


def show_bug_report(console) -> None:
    """Display bug report information and optionally open GitHub issues."""
    import webbrowser
    import questionary

    console.print()
    console.print("[bold cyan]Bug Report[/bold cyan]")
    console.print()
    console.print("Found a bug? We'd love to hear about it!")
    console.print()
    console.print(f"  [bold]Report issues at:[/bold] {GITHUB_ISSUES}")
    console.print()

    try:
        open_browser = questionary.confirm(
            "Open GitHub issues in your browser?",
            default=True,
        ).ask()

        if open_browser:
            webbrowser.open(GITHUB_ISSUES)
            console.print("[green]✓[/green] Opened in browser")
        else:
            console.print("[yellow]Cancelled[/yellow]")
    except KeyboardInterrupt:
        console.print("[yellow]Cancelled[/yellow]")

    console.print()


def show_status(console, app_config: Config, args: Namespace) -> None:
    """Display current session settings."""
    console.print()
    console.print("[bold cyan]Current Session Settings:[/bold cyan]")
    console.print()
    console.print(f"  [bold]Provider:[/bold]      {app_config.provider or 'auto-detect'}")
    console.print(f"  [bold]Model:[/bold]         {app_config.get_model() or 'default'}")
    console.print()
    console.print("[bold cyan]Active Modes:[/bold cyan]")
    console.print()
    console.print(f"  [bold]Skip questions:[/bold] {'ON' if getattr(args, 'skip_questions', False) else 'OFF'}")
    console.print(f"  [bold]Refine mode:[/bold]    {'ON' if args.refine else 'OFF'}")
    console.print()

    configured = app_config.get_configured_providers()
    if configured:
        console.print(f"  [bold]Available providers:[/bold] {', '.join(configured)}")
        console.print()


def handle_session_command(
    command_str: str,
    app_config: Config,
    args: Namespace,
    console,
    notify: MessageSink,
) -> Optional[str]:
    """
    Handle in-session commands like /set, /toggle, /status.

    Returns:
        'reload_provider' if the provider needs to be reloaded,
        'handled' if the command was handled but doesn't need reload,
        None if this is not a session command
    """
    parts = command_str.strip().split()
    if not parts:
        return None

    command = parts[0][1:].lower()  # Remove the '/' and normalize

    if command == "set":
        if len(parts) < 3:
            notify("[yellow]Usage: /set provider <name> or /set model <name>[/yellow]")
            return "handled"

        setting = parts[1].lower()
        value = parts[2]

        if setting == "provider":
            configured = app_config.get_configured_providers()
            if value not in configured:
                notify(f"[red]✗[/red] Provider '{value}' is not configured or available")
                notify(f"[dim]Available providers: {', '.join(configured)}[/dim]")
                return "handled"

            app_config.set_provider(value)
            notify(f"[green]✓[/green] Provider set to '{value}'")
            return "reload_provider"

        elif setting == "model":
            app_config.set_model(value)
            notify(f"[green]✓[/green] Model set to '{value}'")
            return "reload_provider"

        else:
            notify(f"[yellow]Unknown setting: {setting}. Use 'provider' or 'model'.[/yellow]")
            return "handled"

    elif command == "toggle":
        if len(parts) < 2:
            notify("[yellow]Usage: /toggle refine or /toggle skip-questions[/yellow]")
            return "handled"

        mode = parts[1].lower()

        if mode == "refine":
            args.refine = not args.refine
            if args.refine:
                args.skip_questions = False  # Mutually exclusive
            status = "ON" if args.refine else "OFF"
            notify(f"[green]✓[/green] Refine mode is now {status}")
            return "handled"

        elif mode == "skip-questions":
            args.skip_questions = not args.skip_questions
            if args.skip_questions:
                args.refine = False  # Mutually exclusive
            status = "ON" if args.skip_questions else "OFF"
            notify(f"[green]✓[/green] Skip-questions mode is now {status}")
            return "handled"

        else:
            notify(f"[yellow]Unknown mode: {mode}. Use 'refine' or 'skip-questions'.[/yellow]")
            return "handled"

    elif command == "status":
        show_status(console, app_config, args)
        return "handled"

    else:
        # Not a session command, return None to let the existing handler deal with it
        return None


def reload_provider_instance(
    app_config: Config,
    console,
    notify: MessageSink,
) -> Optional[LLMProvider]:
    """
    Reload the provider instance based on current config.

    Returns:
        New provider instance, or None if initialization failed
    """
    provider_name = app_config.provider or "google"
    model_name = app_config.get_model()

    try:
        with console.status(f"[bold blue]🚀 Initializing {provider_name}...", spinner="aesthetic"):
            new_provider = get_provider(provider_name, app_config, model_name)
        notify(f"[green]✓[/green] Successfully initialized {provider_name} with model {model_name}")
        return new_provider
    except Exception as exc:
        sanitized = sanitize_error_message(str(exc))
        notify(f"[red]✗[/red] Failed to initialize provider: {sanitized}")
        logger.exception("Provider reload failed")
        return None
