"""Extract twmcp canonical TOML from MCP JSON configuration files."""

import json
from pathlib import Path

# Known server properties matching config.py:Server dataclass
_KNOWN_PROPS = frozenset({"command", "args", "type", "env", "url", "headers", "tools"})

# Key-name suffixes that indicate secret values
_SECRET_SUFFIXES = ("_token", "_key", "_secret", "_password", "_credentials")

# Agent-specific type names → canonical types
_TYPE_MAP = {"local": "stdio"}


def detect_servers(data: dict) -> dict[str, dict]:
    """Extract servers dict from MCP JSON, auto-detecting the wrapper format.

    Probes in priority order:
    1. data["mcpServers"]  — Claude Desktop / Copilot CLI
    2. data["mcp"]["servers"]  — VS Code
    3. data["servers"]  — IntelliJ / flat

    Raises ValueError if no recognized format or empty servers.
    """
    servers = None

    if "mcpServers" in data:
        servers = data["mcpServers"]
    elif "mcp" in data and isinstance(data["mcp"], dict):
        servers = data["mcp"].get("servers")
    elif "servers" in data:
        servers = data["servers"]

    if not servers:
        raise ValueError(
            "No MCP servers found\n"
            '  Expected one of: "mcpServers", "mcp.servers", or "servers" key'
        )
    return servers


def is_secret_key(key: str) -> bool:
    """Check if a key name suggests it holds a secret value."""
    lower = key.lower().replace("-", "_")
    return any(lower.endswith(suffix) for suffix in _SECRET_SUFFIXES)


def normalize_type(server_type: str) -> str:
    """Map agent-specific type names to canonical types."""
    return _TYPE_MAP.get(server_type, server_type)


def _format_toml_value(value: object) -> str:
    """Format a Python value as a TOML literal."""
    if isinstance(value, str):
        return f'"{value}"'
    if isinstance(value, bool):
        return "true" if value else "false"
    if isinstance(value, (int, float)):
        return str(value)
    if isinstance(value, list):
        items = ", ".join(_format_toml_value(item) for item in value)
        return f"[{items}]"
    return f'"{value}"'


def format_server_toml(
    name: str,
    server: dict,
    *,
    return_secrets: bool = False,
) -> str | tuple[str, set[str]]:
    """Format a single server entry as canonical TOML.

    Returns TOML string. If return_secrets=True, returns (toml_str, secret_names).
    """
    lines: list[str] = []
    secrets: set[str] = set()

    lines.append(f"[servers.{name}]")

    # Emit known properties in canonical order
    server_type = server.get("type", "stdio")
    canonical_type = normalize_type(server_type)

    if "command" in server:
        lines.append(f"command = {_format_toml_value(server['command'])}")
    if "args" in server:
        lines.append(f"args = {_format_toml_value(server['args'])}")
    lines.append(f'type = "{canonical_type}"')
    if "url" in server:
        lines.append(f"url = {_format_toml_value(server['url'])}")
    if "tools" in server:
        lines.append(f"tools = {_format_toml_value(server['tools'])}")

    # Unknown properties as comments
    for key, value in server.items():
        if key not in _KNOWN_PROPS:
            lines.append(f"# unknown: {key} = {json.dumps(value)}")

    # Env sub-table
    env = server.get("env")
    if env:
        lines.append("")
        lines.append(f"[servers.{name}.env]")
        for k, v in env.items():
            if is_secret_key(k):
                secrets.add(k)
                lines.append(f'{k} = "${{{k}}}"')
            else:
                lines.append(f"{k} = {_format_toml_value(v)}")

    # Headers sub-table
    headers = server.get("headers")
    if headers:
        lines.append("")
        lines.append(f"[servers.{name}.headers]")
        for k, v in headers.items():
            if is_secret_key(k):
                secrets.add(k)
                lines.append(f'{k} = "${{{k}}}"')
            else:
                lines.append(f"{k} = {_format_toml_value(v)}")

    toml_str = "\n".join(lines)
    if return_secrets:
        return toml_str, secrets
    return toml_str


def servers_to_toml(servers: dict[str, dict], *, source: str = "") -> str:
    """Convert a servers dict to complete canonical TOML with header comments."""
    all_secrets: set[str] = set()
    server_blocks: list[str] = []

    for name, server_data in servers.items():
        block, secrets = format_server_toml(name, server_data, return_secrets=True)
        server_blocks.append(block)
        all_secrets.update(secrets)

    # Build header
    header_lines: list[str] = []
    header_lines.append(f"# Generated by: twmcp extract {source}")
    if all_secrets:
        var_list = ", ".join(sorted(all_secrets))
        header_lines.append("# Secret placeholders (set these environment variables):")
        header_lines.append(f"#   {var_list}")

    parts = ["\n".join(header_lines)]
    parts.extend(server_blocks)
    return "\n\n".join(parts) + "\n"


def extract_from_file(path: Path) -> str:
    """Read an MCP JSON config file and return canonical TOML string.

    Raises FileNotFoundError if path doesn't exist.
    Raises ValueError if JSON is invalid or no servers found.
    """
    if not path.exists():
        raise FileNotFoundError(f"File not found: {path}")

    text = path.read_text()
    try:
        data = json.loads(text)
    except json.JSONDecodeError as e:
        raise ValueError(f"Invalid JSON: {path}\n  {e}") from e

    servers = detect_servers(data)
    return servers_to_toml(servers, source=str(path))
