"""MCP tool definitions for GDSFactory+.

This module defines the MCP tools that are exposed to AI assistants.
Tools are organized by functionality and phase of implementation.
"""

from __future__ import annotations

from mcp.types import Tool

__all__ = [
    "TOOLS",
    "get_all_tools",
    "get_tool_by_name",
]


# Project discovery tools (for multi-project support)
PROJECT_TOOLS: list[Tool] = [
    Tool(
        name="list_projects",
        description=(
            "List all active GDSFactory+ projects. Returns information about "
            "all running servers including project name, path, port, PID, and PDK. "
            "Use this to discover which projects are available for interaction."
        ),
        inputSchema={
            "type": "object",
            "properties": {},
        },
    ),
    Tool(
        name="get_project_info",
        description=(
            "Get detailed information about a specific project. Returns metadata "
            "including project name, path, port, PID, PDK, and version. "
            "Use this to get information about a running project."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "project": {
                    "type": "string",
                    "description": (
                        "Project name or path. Can be the project directory name "
                        "or full path."
                    ),
                },
            },
            "required": ["project"],
        },
    ),
]

# Standard optional project parameter for all tools
PROJECT_PARAM_SCHEMA = {
    "project": {
        "type": "string",
        "description": (
            "Optional project name or path to route this request to a specific "
            "server. If not provided, routes to the default server. "
            "Use list_projects to see available projects."
        ),
    },
}


def _add_project_param(schema: dict) -> dict:
    """Add optional project parameter to a tool schema.

    Args:
        schema: Original input schema

    Returns:
        Schema with project parameter added
    """
    if "properties" not in schema:
        schema["properties"] = {}
    schema["properties"].update(PROJECT_PARAM_SCHEMA)
    return schema


# Phase 1: Core Building Tools (5 tools)
CORE_TOOLS: list[Tool] = [
    Tool(
        name="build_cell",
        description=(
            "Build a single GDS cell by name. This creates the physical layout "
            "file (.gds) for a photonic component. The build happens in the "
            "background and the GDS file will be saved to the project build "
            "directory."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Name of the cell/component to build",
                    },
                    "with_metadata": {
                        "type": "boolean",
                        "description": (
                            "Include metadata in the GDS file (default: true)"
                        ),
                        "default": True,
                    },
                    "register": {
                        "type": "boolean",
                        "description": (
                            "Re-register the cell in the KLayout cache (default: true)"
                        ),
                        "default": True,
                    },
                },
                "required": ["name"],
            }
        ),
    ),
    Tool(
        name="build_cells",
        description=(
            "Build multiple GDS cells by name in one operation. This is more "
            "efficient than building cells one at a time. All cells are built "
            "in the background and saved to the project build directory."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "names": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "List of cell/component names to build",
                    },
                    "with_metadata": {
                        "type": "boolean",
                        "description": (
                            "Include metadata in the GDS files (default: true)"
                        ),
                        "default": True,
                    },
                    "register": {
                        "type": "boolean",
                        "description": (
                            "Re-register the cells in the KLayout cache (default: true)"
                        ),
                        "default": True,
                    },
                },
                "required": ["names"],
            }
        ),
    ),
    Tool(
        name="list_cells",
        description=(
            "List all available cells/components that can be built. Returns "
            "the names of all registered component factories in the current PDK. "
            "Use this to discover what components are available before building."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {},
            }
        ),
    ),
    Tool(
        name="get_cell_info",
        description=(
            "Get detailed information about a specific cell/component. Returns "
            "metadata including the source file, parameters, and other details "
            "about the component factory."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Name of the cell/component to get info about",
                    },
                },
                "required": ["name"],
            }
        ),
    ),
    Tool(
        name="download_gds",
        description=(
            "Download a GDS file from the project build directory. Returns the "
            "file path to the downloaded GDS file. The file must have been "
            "previously built using build_cell or build_cells."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": (
                            "Relative path to the GDS file (without .gds extension). "
                            "For example, 'mzi' or 'components/coupler'"
                        ),
                    },
                },
                "required": ["path"],
            }
        ),
    ),
]

# Phase 2: Verification Tools
VERIFICATION_TOOLS: list[Tool] = [
    Tool(
        name="check_drc",
        description=(
            "Run a full DRC (Design Rule Check) on a GDS file. This uploads "
            "the file to a remote DRC server and runs comprehensive design rule "
            "verification for the specified PDK and process. Use this for "
            "complete design rule validation. Returns XML results showing all "
            "DRC violations."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": (
                            "Path to the GDS file to check. Can be absolute or "
                            "relative to the project directory."
                        ),
                    },
                    "pdk": {
                        "type": "string",
                        "description": (
                            "PDK to use for the check. If not specified, uses the "
                            "default PDK from settings."
                        ),
                    },
                    "process": {
                        "type": "string",
                        "description": (
                            "Process variant for DRC rules. If not specified, uses "
                            "the default process from settings."
                        ),
                    },
                    "timeout": {
                        "type": "integer",
                        "description": (
                            "Timeout in seconds for the DRC check. If not specified, "
                            "uses the default timeout from settings."
                        ),
                    },
                    "host": {
                        "type": "string",
                        "description": (
                            "API host for the DRC server. If not specified, uses "
                            "the default host from settings."
                        ),
                    },
                },
                "required": ["path"],
            }
        ),
    ),
    Tool(
        name="check_connectivity",
        description=(
            "Run a local connectivity check on a GDS file. This verifies that "
            "all layers are properly connected and identifies any connectivity "
            "violations. This is a fast, local check (does not require uploading "
            "to a remote server). Use this to quickly check for disconnected "
            "components. Returns XML results showing connectivity issues."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": (
                            "Path to the GDS file to check. Can be absolute or "
                            "relative to the project directory."
                        ),
                    },
                },
                "required": ["path"],
            }
        ),
    ),
    Tool(
        name="check_lvs",
        description=(
            "Run LVS (Layout vs. Schematic) verification on a cell against a "
            "reference netlist. This compares the physical layout to the "
            "schematic representation to ensure they match. Returns XML results "
            "showing any mismatches between layout and schematic."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "cell": {
                        "type": "string",
                        "description": "Name of the cell to verify",
                    },
                    "netpath": {
                        "type": "string",
                        "description": (
                            "Path to the reference netlist file to compare against"
                        ),
                    },
                    "cellargs": {
                        "type": "string",
                        "description": (
                            "Optional cell arguments as a JSON string. "
                            "Default is empty string."
                        ),
                        "default": "",
                    },
                },
                "required": ["cell", "netpath"],
            }
        ),
    ),
]

# Phase 3: SPICE Workflow Tools (to be implemented)
SPICE_TOOLS: list[Tool] = []

# Phase 4: Simulation & Advanced Tools
ADVANCED_TOOLS: list[Tool] = [
    Tool(
        name="simulate_component",
        description=(
            "Run a SAX circuit simulation on a photonic component by name. "
            "This simulates the optical behavior of the component using its "
            "SAX model. Returns S-parameters showing how light propagates "
            "through the component's ports. Use this to analyze component "
            "performance before fabrication."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": (
                            "Name of the component/cell to simulate. The component "
                            "must have a SAX model defined."
                        ),
                    },
                },
                "required": ["name"],
            }
        ),
    ),
    Tool(
        name="get_port_center",
        description=(
            "Get the center coordinates (x, y) of a specific port in a component "
            "instance. This is useful for positioning components, routing waveguides, "
            "or analyzing layout geometry. Returns the physical coordinates in "
            "microns."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "netlist": {
                        "type": "string",
                        "description": (
                            "Name of the component/netlist containing the instance"
                        ),
                    },
                    "instance": {
                        "type": "string",
                        "description": "Name of the instance within the netlist",
                    },
                    "port": {
                        "type": "string",
                        "description": "Name of the port to get coordinates for",
                    },
                },
                "required": ["netlist", "instance", "port"],
            }
        ),
    ),
    Tool(
        name="generate_bbox",
        description=(
            "Generate a bounding box GDS file from an input GDS. This creates "
            "a simplified version of the layout with only a bounding box on "
            "specified layers. Useful for creating abstract views, floorplanning, "
            "or hierarchical design. Can optionally preserve specific layers and "
            "ports."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": (
                            "Path to the input GDS file. Can be absolute or relative "
                            "to the project directory."
                        ),
                    },
                    "outpath": {
                        "type": "string",
                        "description": (
                            "Output path for the bounding box GDS. If not specified, "
                            "uses the input filename with '-bbox' suffix."
                        ),
                        "default": "",
                    },
                    "layers_to_keep": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": (
                            "List of layer names to preserve in the output. "
                            "Other layers will be replaced by the bounding box."
                        ),
                        "default": [],
                    },
                    "bbox_layer": {
                        "type": "array",
                        "items": {"type": "integer"},
                        "description": (
                            "Layer (as [layer, datatype]) to use for the bounding box. "
                            "Default is [99, 0]."
                        ),
                        "default": [99, 0],
                    },
                    "ignore_ports": {
                        "type": "boolean",
                        "description": (
                            "If true, do not include ports in the output. "
                            "Default is false."
                        ),
                        "default": False,
                    },
                },
                "required": ["path"],
            }
        ),
    ),
    Tool(
        name="freeze_cell",
        description=(
            "Freeze a parametric Python cell as a static schematic netlist. "
            "This converts a gdsfactory component with specific parameters into "
            "a fixed netlist representation in YAML format. Useful for creating "
            "versioned snapshots of parametric designs or preparing components "
            "for simulation workflows."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {
                    "cell_name": {
                        "type": "string",
                        "description": "Name of the cell/component to freeze",
                    },
                    "kwargs": {
                        "type": "object",
                        "description": (
                            "Optional keyword arguments to pass to the component "
                            "factory. Use this to specify parameter values when "
                            "freezing the cell. Default is empty (use default params)."
                        ),
                        "default": {},
                    },
                },
                "required": ["cell_name"],
            }
        ),
    ),
    Tool(
        name="get_pdk_info",
        description=(
            "Get information about the current PDK (Process Design Kit) in use. "
            "Returns metadata including PDK name, project name, project path, "
            "server port, and version. Use this to verify which PDK is active "
            "and get project configuration details."
        ),
        inputSchema=_add_project_param(
            {
                "type": "object",
                "properties": {},
            }
        ),
    ),
]

# All tools (Phase 1 + Project tools)
TOOLS: list[Tool] = [
    *PROJECT_TOOLS,  # Project discovery tools (always available)
    *CORE_TOOLS,
    *VERIFICATION_TOOLS,
    *SPICE_TOOLS,
    *ADVANCED_TOOLS,
]


def get_all_tools() -> list[Tool]:
    """Get all available MCP tools.

    Returns:
        List of all tool definitions
    """
    return TOOLS


def get_tool_by_name(name: str) -> Tool | None:
    """Get a tool by name.

    Args:
        name: Tool name

    Returns:
        Tool definition or None if not found
    """
    for tool in TOOLS:
        if tool.name == name:
            return tool
    return None
