"""
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 pathlib import Path
from typing import Optional

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

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

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(f"\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)
