"""
MCP CLI Commands - Manage MCP server configurations

Provides commands for:
- mcp add <name> <command> [args...] - Add MCP server
- mcp list - List configured servers
- mcp remove <name> - Remove a server
- mcp connect <name> - Test connection to a server
- mcp tools [server] - List available tools
"""

import asyncio
import sys
from typing import Optional

import click
from rich.console import Console
from rich.panel import Panel
from rich.table import Table

from groknroll.mcp import (
    MCPRegistry,
    MCPServerConfig,
    MCPTransportType,
)

console = Console()


@click.group()
def mcp():
    """Manage MCP (Model Context Protocol) servers"""
    pass


@mcp.command()
@click.argument("name")
@click.argument("command")
@click.argument("args", nargs=-1)
@click.option(
    "--env",
    "-e",
    multiple=True,
    help="Environment variable in KEY=VALUE format",
)
@click.option(
    "--transport",
    "-t",
    type=click.Choice(["stdio", "sse", "http"]),
    default="stdio",
    help="Transport type",
)
@click.option("--url", help="URL for SSE/HTTP transport")
@click.option("--description", "-d", default="", help="Server description")
@click.option("--global", "global_config", is_flag=True, help="Save to global config")
def add(
    name: str,
    command: str,
    args: tuple,
    env: tuple,
    transport: str,
    url: Optional[str],
    description: str,
    global_config: bool,
):
    """
    Add an MCP server configuration

    Examples:

        # Add filesystem server
        groknroll mcp add filesystem npx -y @modelcontextprotocol/server-filesystem /path

        # Add with environment variables
        groknroll mcp add postgres npx -y @modelcontextprotocol/server-postgres -e DATABASE_URL=postgres://...

        # Add SSE server
        groknroll mcp add remote --transport sse --url http://localhost:3000

        # Add with description
        groknroll mcp add custom-server python server.py -d "My custom MCP server"
    """
    # Parse environment variables
    env_dict = {}
    for e in env:
        if "=" in e:
            key, value = e.split("=", 1)
            env_dict[key] = value
        else:
            console.print(f"[bold red]Error:[/bold red] Invalid env var format: {e}")
            console.print("Use KEY=VALUE format")
            sys.exit(1)

    # Create config
    config = MCPServerConfig(
        name=name,
        command=command,
        args=list(args),
        env=env_dict,
        transport=MCPTransportType(transport),
        url=url,
        description=description,
        enabled=True,
    )

    # Add to registry
    registry = MCPRegistry()
    try:
        registry.add_server(config, save=True, global_config=global_config)
        console.print(f"[bold green]✓ Added MCP server:[/bold green] {name}")
        console.print(f"  [dim]Command:[/dim] {command} {' '.join(args)}")
        if description:
            console.print(f"  [dim]Description:[/dim] {description}")
        console.print(f"\n[dim]Run 'groknroll mcp connect {name}' to test the connection[/dim]")
    except ValueError as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@mcp.command("list")
@click.option("--all", "-a", "show_all", is_flag=True, help="Show all details")
def list_servers(show_all: bool):
    """List configured MCP servers"""
    registry = MCPRegistry()
    servers = registry.list_servers()

    if not servers:
        console.print("[yellow]No MCP servers configured[/yellow]")
        console.print(
            "\n[dim]Add a server with: groknroll mcp add <name> <command> [args...][/dim]"
        )
        return

    # Create table
    table = Table(title="MCP Servers", show_header=True)
    table.add_column("Name", style="cyan")
    table.add_column("Status", style="green")
    table.add_column("Transport", style="blue")
    if show_all:
        table.add_column("Command")
        table.add_column("Description")

    for server in servers:
        status = "[green]enabled" if server.enabled else "[red]disabled"
        connected = registry.is_connected(server.name)
        if connected:
            status = "[bold green]connected"

        row = [
            server.name,
            status,
            server.transport.value,
        ]

        if show_all:
            cmd = f"{server.command} {' '.join(server.args)}"
            row.extend([cmd[:40] + "..." if len(cmd) > 40 else cmd, server.description])

        table.add_row(*row)

    console.print()
    console.print(table)
    console.print(f"\n[dim]Total: {len(servers)} server(s)[/dim]")


@mcp.command()
@click.argument("name")
@click.option("--force", "-f", is_flag=True, help="Skip confirmation")
def remove(name: str, force: bool):
    """Remove an MCP server configuration"""
    registry = MCPRegistry()

    # Check if server exists
    if not registry.get_server(name):
        console.print(f"[bold red]Error:[/bold red] Server '{name}' not found")
        sys.exit(1)

    # Confirm removal
    if not force:
        console.print(f"[bold yellow]Remove MCP server '{name}'?[/bold yellow]")
        response = input("Continue? [y/N]: ").strip().lower()
        if response not in ["y", "yes"]:
            console.print("[yellow]Cancelled[/yellow]")
            return

    # Remove
    try:
        registry.remove_server(name)
        console.print(f"[bold green]✓ Removed MCP server:[/bold green] {name}")
    except KeyError as e:
        console.print(f"[bold red]Error:[/bold red] {e}")
        sys.exit(1)


@mcp.command()
@click.argument("name")
def connect(name: str):
    """Test connection to an MCP server"""
    registry = MCPRegistry()

    # Check if server exists
    config = registry.get_server(name)
    if not config:
        console.print(f"[bold red]Error:[/bold red] Server '{name}' not found")
        sys.exit(1)

    console.print(f"[bold cyan]Connecting to {name}...[/bold cyan]")

    async def test_connection():
        try:
            info = await registry.connect(name)

            console.print("\n[bold green]✓ Connected successfully![/bold green]")
            console.print(f"  [cyan]Server:[/cyan] {info.name} v{info.version}")
            console.print(
                f"  [cyan]Capabilities:[/cyan] {', '.join(c.value for c in info.capabilities)}"
            )

            # Show tools
            tools = registry.get_tools(name)
            if tools:
                console.print(f"  [cyan]Tools:[/cyan] {len(tools)}")
                for tool in tools[:5]:
                    console.print(f"    - {tool.name}: {tool.description[:50]}...")
                if len(tools) > 5:
                    console.print(f"    ... and {len(tools) - 5} more")

            # Disconnect
            await registry.disconnect(name)

        except Exception as e:
            console.print(f"\n[bold red]✗ Connection failed:[/bold red] {e}")
            sys.exit(1)

    asyncio.run(test_connection())


@mcp.command()
@click.argument("server", required=False)
def tools(server: Optional[str]):
    """List available tools from MCP servers"""
    registry = MCPRegistry()

    async def list_tools():
        # Connect to servers
        if server:
            if not registry.get_server(server):
                console.print(f"[bold red]Error:[/bold red] Server '{server}' not found")
                sys.exit(1)

            console.print(f"[dim]Connecting to {server}...[/dim]")
            try:
                await registry.connect(server)
            except Exception as e:
                console.print(f"[bold red]Error:[/bold red] {e}")
                sys.exit(1)
        else:
            console.print("[dim]Connecting to all enabled servers...[/dim]")
            await registry.connect_all()

        # Get tools
        all_tools = registry.list_all_tools()

        if not all_tools:
            console.print("[yellow]No tools available[/yellow]")
            return

        # Display tools
        for server_name, tools_list in all_tools.items():
            console.print()
            console.print(
                Panel.fit(
                    f"[bold cyan]{server_name}[/bold cyan] ({len(tools_list)} tools)",
                    border_style="cyan",
                )
            )

            table = Table(show_header=True)
            table.add_column("Tool", style="green")
            table.add_column("Description")
            table.add_column("Parameters")

            for tool in tools_list:
                params = ", ".join(f"{p.name}{'*' if p.required else ''}" for p in tool.parameters)
                table.add_row(
                    tool.name,
                    tool.description[:60] + "..."
                    if len(tool.description) > 60
                    else tool.description,
                    params[:30] + "..." if len(params) > 30 else params,
                )

            console.print(table)

        # Disconnect
        await registry.disconnect_all()

    asyncio.run(list_tools())


@mcp.command()
@click.argument("name")
def enable(name: str):
    """Enable an MCP server"""
    registry = MCPRegistry()

    try:
        registry.enable_server(name)
        console.print(f"[bold green]✓ Enabled MCP server:[/bold green] {name}")
    except KeyError:
        console.print(f"[bold red]Error:[/bold red] Server '{name}' not found")
        sys.exit(1)


@mcp.command()
@click.argument("name")
def disable(name: str):
    """Disable an MCP server"""
    registry = MCPRegistry()

    try:
        registry.disable_server(name)
        console.print(f"[bold green]✓ Disabled MCP server:[/bold green] {name}")
    except KeyError:
        console.print(f"[bold red]Error:[/bold red] Server '{name}' not found")
        sys.exit(1)
