"""CLI registry orchestration for MCP registration across all supported clients."""

from __future__ import annotations

import shutil
import subprocess
from pathlib import Path

from .claude_internal import write_claude_internal_config, remove_claude_internal_config
from .codex_internal import write_codex_internal_config, remove_codex_internal_config
from .gemini_internal import write_gemini_internal_config, remove_gemini_internal_config
from .openclaw import write_openclaw_config, remove_openclaw_config


def register_all(
    *,
    server_name: str,
    runtime: str,
    launcher_path: Path | str,
) -> None:
    """Register MCP server with all detected CLIs.
    
    Args:
        server_name: Server name for registration (e.g., "reddit-mcp")
        runtime: Runtime executable (e.g., "python3")
        launcher_path: Path to launcher script
    """
    launcher_path = Path(launcher_path)
    
    cli_candidates = [
        (
            "claude-internal",
            "Claude Code (internal)",
            lambda bin_path: [bin_path, "mcp", "add", "-s", "user", server_name, "--", runtime, str(launcher_path), "serve"],
        ),
        (
            "claude",
            "Claude Code",
            lambda bin_path: [bin_path, "mcp", "add", "-s", "user", server_name, "--", runtime, str(launcher_path), "serve"],
        ),
        (
            "codex",
            "Codex CLI / Codex App",
            lambda bin_path: [bin_path, "mcp", "add", server_name, "--", runtime, str(launcher_path), "serve"],
        ),
        ("codex-internal", "Codex CLI (internal)", None),
        (
            "gemini-internal",
            "Gemini CLI (internal)",
            lambda bin_path: [bin_path, "mcp", "add", "-s", "user", server_name, runtime, str(launcher_path), "serve"],
        ),
        (
            "gemini",
            "Gemini CLI",
            lambda bin_path: [bin_path, "mcp", "add", "-s", "user", server_name, runtime, str(launcher_path), "serve"],
        ),
        (
            "opencode",
            "OpenCode",
            lambda bin_path: [bin_path, "mcp", "add", server_name, "--", runtime, str(launcher_path), "serve"],
        ),
    ]

    registered = False
    for bin_name, label, build_cmd in cli_candidates:
        bin_path = shutil.which(bin_name)
        if not bin_path:
            continue
        print(f"\n🔗 Registering with {label} ({bin_name})...")
        if build_cmd is None:
            print(f"   ⚠️  {label} detected but requires manual MCP config.")
            continue
        try:
            result = subprocess.run(build_cmd(bin_path), capture_output=True, text=True, timeout=15)
            if result.returncode == 0:
                print(f"   ✅ Registered with {label}")
                registered = True
            else:
                stderr = result.stderr.strip()
                print(f"   ⚠️  {label}: {stderr or 'registration failed'}")
        except Exception as e:
            print(f"   ⚠️  {label}: {e}")

    # codex-internal: direct TOML write
    try:
        status = write_claude_internal_config(
            server_name=server_name,
            runtime=runtime,
            launcher_path=str(launcher_path),
        )
        suffix = "created" if status == "created" else "updated"
        print(f"\n🔗 Registering with Claude Code (internal)...")
        print(f"   ✅ Registered with Claude Code (internal) ({suffix} local config)")
        registered = True
    except Exception as e:
        print(f"\n🔗 Registering with Claude Code (internal)...")
        print(f"   ⚠️  Claude Code (internal): {e}")

    try:
        write_codex_internal_config(
            server_name=server_name,
            runtime=runtime,
            launcher_path=str(launcher_path),
        )
        print(f"\n🔗 Registering with Codex CLI (internal)...")
        print(f"   ✅ Registered with Codex CLI (internal) (direct TOML write)")
        registered = True
    except Exception as e:
        print(f"\n🔗 Registering with Codex CLI (internal)...")
        print(f"   ⚠️  Codex CLI (internal): {e}")

    try:
        status = write_gemini_internal_config(
            server_name=server_name,
            runtime=runtime,
            launcher_path=str(launcher_path),
        )
        suffix = "created" if status == "created" else "updated"
        print(f"\n🔗 Registering with Gemini CLI (internal)...")
        print(f"   ✅ Registered with Gemini CLI (internal) ({suffix} local config)")
        registered = True
    except Exception as e:
        print(f"\n🔗 Registering with Gemini CLI (internal)...")
        print(f"   ⚠️  Gemini CLI (internal): {e}")

    # openclaw: try mcporter CLI, fallback to JSON write
    try:
        status = write_openclaw_config(
            server_name=server_name,
            runtime=runtime,
            launcher_path=str(launcher_path),
        )
        suffix = "created" if status == "created" else "updated"
        print(f"\n🔗 Registering with OpenClaw...")
        print(f"   ✅ Registered with OpenClaw ({suffix} mcporter.json)")
        registered = True
    except Exception as e:
        print(f"\n🔗 Registering with OpenClaw...")
        print(f"   ⚠️  OpenClaw: {e}")

    if not registered:
        print("\nℹ️  No supported CLI found. Add manually to your AI client.")


def unregister_all(*, server_name: str) -> None:
    """Remove MCP server registration from all detected CLIs.
    
    Args:
        server_name: Server name to unregister
    """
    print("\n🧹 Uninstalling MCP registrations\n")
    print("Removing MCP client registrations...")

    cli_candidates = [
        ("claude-internal", "Claude Code (internal)", ["claude-internal", "mcp", "remove", "-s", "user", server_name]),
        ("claude", "Claude Code", ["claude", "mcp", "remove", "-s", "user", server_name]),
        ("codex", "Codex CLI / Codex App", ["codex", "mcp", "remove", server_name]),
        ("gemini-internal", "Gemini CLI (internal)", ["gemini-internal", "mcp", "remove", "-s", "user", server_name]),
        ("gemini", "Gemini CLI", ["gemini", "mcp", "remove", "-s", "user", server_name]),
        ("opencode", "OpenCode", ["opencode", "mcp", "remove", server_name]),
    ]

    for binary, label, command in cli_candidates:
        if shutil.which(binary):
            try:
                result = subprocess.run(command, capture_output=True, text=True, timeout=15)
                if result.returncode == 0:
                    print(f"  ✅ Removed MCP registration from {label}")
                else:
                    stderr = (result.stderr or "").lower()
                    if any(text in stderr for text in ("not found", "no server", "unknown")):
                        print(f"  ℹ️  {label} did not have {server_name} registered")
                    else:
                        print(f"  ⚠️  Failed to remove MCP registration from {label}")
            except (OSError, subprocess.SubprocessError):
                print(f"  ⚠️  Failed to remove MCP registration from {label}")

    # codex-internal: direct TOML removal
    status = remove_claude_internal_config(server_name=server_name)
    if status == "removed":
        print(f"  ✅ Removed MCP registration from Claude Code (internal)")
    else:
        print(f"  ℹ️  Claude Code (internal) did not have {server_name} registered")

    try:
        remove_codex_internal_config(server_name=server_name)
        print(f"  ✅ Removed MCP registration from Codex CLI (internal)")
    except Exception:
        print(f"  ℹ️  Codex CLI (internal) did not have {server_name} registered")

    status = remove_gemini_internal_config(server_name=server_name)
    if status == "removed":
        print(f"  ✅ Removed MCP registration from Gemini CLI (internal)")
    else:
        print(f"  ℹ️  Gemini CLI (internal) did not have {server_name} registered")

    # openclaw: JSON removal
    status = remove_openclaw_config(server_name=server_name)
    if status == "removed":
        print(f"  ✅ Removed MCP registration from OpenClaw")
    else:
        print(f"  ℹ️  OpenClaw did not have {server_name} registered")
