# src/dattos_cli/commands/mcp_cmd.py
from __future__ import annotations

import json
import os
import subprocess
import sys
from pathlib import Path
from typing import Optional

import typer

from dattos_cli.output import print_json

app = typer.Typer(help="MCP server management.", no_args_is_help=True)

MCP_ENTRY = {
    "command": "dattos-mcp",
    "args": [],
}

TARGETS = {
    "claude-code": "Claude Code",
    "claude-desktop": "Claude Desktop",
    "cursor": "Cursor",
    "vscode": "VS Code / GitHub Copilot",
    "windsurf": "Windsurf",
    "gemini": "Gemini CLI",
    "chatgpt": "ChatGPT (remote only)",
    "copilot-studio": "Microsoft Copilot Studio (remote only)",
}


def _get_config_path(target: str) -> Path:
    """Return the MCP config file path for a target."""
    home = Path.home()
    platform = sys.platform

    if target == "claude-desktop":
        if platform == "win32":
            return Path(os.environ.get("APPDATA", "")) / "Claude" / "claude_desktop_config.json"
        elif platform == "darwin":
            return home / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json"
        return home / ".config" / "Claude" / "claude_desktop_config.json"

    if target == "cursor":
        return home / ".cursor" / "mcp.json"

    if target == "vscode":
        return Path(".vscode") / "mcp.json"

    if target == "windsurf":
        return home / ".codeium" / "windsurf" / "mcp_config.json"

    if target == "gemini":
        return home / ".gemini" / "settings.json"

    raise ValueError(f"No config path for target: {target}")


def _write_mcp_config(path: Path, target: str) -> None:
    """Add the dattos MCP server entry to a JSON config file."""
    config: dict = {}
    if path.exists():
        # Guard against oversized or malformed files
        if path.stat().st_size > 1_000_000:
            typer.echo(f"Error: config file too large (>1MB): {path}", err=True)
            raise typer.Exit(1)
        try:
            config = json.loads(path.read_text(encoding="utf-8"))
        except json.JSONDecodeError:
            typer.echo(f"Error: invalid JSON in {path}", err=True)
            raise typer.Exit(1)

    # VS Code uses "servers", everyone else uses "mcpServers"
    key = "servers" if target == "vscode" else "mcpServers"
    if key not in config:
        config[key] = {}

    config[key]["dattos"] = MCP_ENTRY

    path.parent.mkdir(parents=True, exist_ok=True)
    # Atomic write: write to temp file then rename
    tmp = path.with_suffix(".tmp")
    tmp.write_text(json.dumps(config, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
    tmp.replace(path)


def _install_claude_code() -> None:
    """Register MCP server via claude CLI."""
    try:
        subprocess.run(
            ["claude", "mcp", "add", "--transport", "stdio", "dattos", "--", "dattos-mcp"],
            check=True,
        )
        typer.echo("Dattos MCP server installed in Claude Code.")
    except FileNotFoundError:
        typer.echo("Error: 'claude' CLI not found in PATH.", err=True)
        typer.echo("Install it first: https://docs.anthropic.com/en/docs/claude-code", err=True)
        raise typer.Exit(1)
    except subprocess.CalledProcessError:
        typer.echo("Error: failed to register MCP server.", err=True)
        raise typer.Exit(1)


def _show_remote_instructions(target: str) -> None:
    """Show manual setup instructions for remote-only targets."""
    if target == "chatgpt":
        typer.echo("ChatGPT only supports remote MCP servers (Streamable HTTP).")
        typer.echo()
        typer.echo("To connect, you need a publicly accessible dattos-mcp server.")
        typer.echo("Then in ChatGPT:")
        typer.echo("  1. Go to Settings > Apps & Connectors > Advanced settings")
        typer.echo("  2. Enable Developer Mode")
        typer.echo("  3. Go to Settings > Connectors > Create")
        typer.echo("  4. Enter your remote MCP server URL")
    elif target == "copilot-studio":
        typer.echo("Copilot Studio only supports remote MCP servers (Streamable HTTP).")
        typer.echo()
        typer.echo("To connect, you need a publicly accessible dattos-mcp server.")
        typer.echo("Then in Copilot Studio:")
        typer.echo("  1. Open your agent")
        typer.echo("  2. Go to Tools > Add a tool > New tool > Model Context Protocol")
        typer.echo("  3. Enter your remote MCP server URL")
        typer.echo("  4. Configure authentication (API Key or OAuth 2.0)")


@app.command("install")
def install(
    target: Optional[str] = typer.Argument(
        None,
        help="Target tool: claude-code, claude-desktop, cursor, vscode, windsurf, gemini, chatgpt, copilot-studio",
    ),
):
    """Install the Dattos MCP server in an AI tool."""
    if target is None:
        typer.echo("Available targets:")
        typer.echo()
        for key, name in TARGETS.items():
            typer.echo(f"  {key:<20} {name}")
        typer.echo()
        typer.echo("Usage: dattos mcp install <target>")
        raise typer.Exit(0)

    if target not in TARGETS:
        typer.echo(f"Unknown target: {target}", err=True)
        typer.echo(f"Available: {', '.join(TARGETS)}", err=True)
        raise typer.Exit(1)

    # Remote-only targets
    if target in ("chatgpt", "copilot-studio"):
        _show_remote_instructions(target)
        raise typer.Exit(0)

    # Claude Code uses its own CLI
    if target == "claude-code":
        _install_claude_code()
        raise typer.Exit(0)

    # All other targets: write JSON config
    path = _get_config_path(target)
    _write_mcp_config(path, target)
    print_json({"status": "installed", "target": target, "config": str(path)})
    typer.echo(f"Dattos MCP server installed in {TARGETS[target]}.")
    typer.echo(f"Config: {path}")
