from __future__ import annotations

import json
from pathlib import Path
from typing import Literal

from pydantic import BaseModel, Field


class McpServerConfig(BaseModel):
    """Configuration for a single MCP server."""

    transport: Literal["stdio", "sse"] = "stdio"

    # stdio fields
    command: str | None = None
    args: list[str] = Field(default_factory=list)
    env: dict[str, str] | None = None
    cwd: str | None = None

    # sse fields
    url: str | None = None
    headers: dict[str, str] | None = None

    # tool groups: name -> list of tool names exposed by this server.
    # Profiles reference groups by name instead of listing individual tools.
    groups: dict[str, list[str]] = Field(default_factory=dict)

    # Overlay instructions injected into Navi's system prompt alongside the
    # instructions provided by the MCP server itself during the initialize handshake.
    instructions: str | None = None

    @property
    def is_stdio(self) -> bool:
        return self.transport == "stdio"

    @property
    def is_sse(self) -> bool:
        return self.transport == "sse"


def load_mcp_servers(path: str | Path | None = None) -> dict[str, McpServerConfig]:
    """Load MCP server configurations from a JSON file.

    Default path is ``mcp_servers.json`` in the current working directory.
    Returns an empty dict if the file does not exist.
    """
    if path is None:
        path = Path("mcp_servers.json")
    else:
        path = Path(path)

    if not path.exists():
        return {}

    raw = json.loads(path.read_text(encoding="utf-8"))
    return {name: McpServerConfig.model_validate(cfg) for name, cfg in raw.items()}


def save_mcp_servers(configs: dict[str, McpServerConfig], path: str | Path | None = None) -> None:
    """Write MCP server configurations to a JSON file.

    Default path is ``mcp_servers.json`` in the current working directory.
    """
    if path is None:
        path = Path("mcp_servers.json")
    else:
        path = Path(path)

    raw = {name: cfg.model_dump() for name, cfg in configs.items()}
    path.write_text(json.dumps(raw, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
