"""Tool namespace conflict detection for MCP servers.

Pure logic: detects duplicate tool names across MCP servers.
No I/O imports.
"""

from deal import post, pre


__all__ = ["detect_tool_conflicts", "format_conflict_warnings"]


@pre(lambda server_tools: isinstance(server_tools, dict))
@post(lambda result: isinstance(result, dict))
def detect_tool_conflicts(server_tools: dict[str, list[str]]) -> dict[str, list[str]]:
    """Detect tool name conflicts across MCP servers.

    Finds tools that appear in multiple servers. When a tool name exists in
    multiple servers, it creates a conflict. The server lists are sorted
    deterministically to ensure consistent output.

    Args:
        server_tools: Dictionary mapping server names to lists of tool names.

    Returns:
        Dictionary mapping tool names to sorted lists of server names
        where conflicts exist. Only includes tools with conflicts (2+ servers).

    Examples:
        Single server - no conflicts:
        >>> detect_tool_conflicts({"server_a": ["tool1", "tool2"]})
        {}

        Two servers with no overlap:
        >>> result = detect_tool_conflicts({"server_a": ["tool1"], "server_b": ["tool2"]})
        >>> result
        {}

        Tool in multiple servers - detects conflict:
        >>> result = detect_tool_conflicts({"server_a": ["greet"], "server_b": ["greet"]})
        >>> result
        {'greet': ['server_a', 'server_b']}

        Multiple conflicts:
        >>> result = detect_tool_conflicts({
        ...     "server_a": ["tool1", "tool2"],
        ...     "server_b": ["tool2", "tool3"],
        ...     "server_c": ["tool1", "tool3"]
        ... })
        >>> result["tool1"]
        ['server_a', 'server_c']
        >>> result["tool2"]
        ['server_a', 'server_b']
        >>> result["tool3"]
        ['server_b', 'server_c']

        Empty server list:
        >>> result = detect_tool_conflicts({"server_a": []})
        >>> result
        {}

        Empty server_tools:
        >>> detect_tool_conflicts({})
        {}
    """
    # Build reverse index: tool_name -> list of servers
    tool_to_servers: dict[str, list[str]] = {}

    for server_name, tools in server_tools.items():
        for tool_name in tools:
            if tool_name not in tool_to_servers:
                tool_to_servers[tool_name] = []
            tool_to_servers[tool_name].append(server_name)

    # Filter to only tools with conflicts (2+ servers) and sort server lists
    conflicts: dict[str, list[str]] = {}
    for tool_name, servers in tool_to_servers.items():
        if len(servers) > 1:
            conflicts[tool_name] = sorted(servers)

    return conflicts


@pre(lambda conflicts: isinstance(conflicts, dict))
@post(lambda result: result is None or isinstance(result, str))
def format_conflict_warnings(conflicts: dict[str, list[str]]) -> str | None:
    """Format conflict warnings for display.

    Converts a conflicts dictionary into a human-readable warning message.
    Returns None if there are no conflicts.

    Args:
        conflicts: Dictionary mapping tool names to sorted lists of server names.

    Returns:
        Formatted warning string, or None if no conflicts exist.

    Examples:
        No conflicts:
        >>> format_conflict_warnings({})

        Single conflict:
        >>> msg = format_conflict_warnings({"greet": ["server_a", "server_b"]})
        >>> "greet" in msg
        True
        >>> "server_a" in msg
        True
        >>> "server_b" in msg
        True

        Multiple conflicts:
        >>> msg = format_conflict_warnings({
        ...     "tool1": ["server_a", "server_b"],
        ...     "tool2": ["server_a", "server_b", "server_c"]
        ... })
        >>> "tool1" in msg
        True
        >>> "tool2" in msg
        True
        >>> msg.count("server_a")  # Both conflicts mention server_a
        2
    """
    if not conflicts:
        return None

    lines = ["Tool name conflicts detected:", ""]

    for tool_name in sorted(conflicts.keys()):
        servers = conflicts[tool_name]
        servers_str = ", ".join(servers)
        lines.append(f"  - '{tool_name}' defined in: {servers_str}")

    return "\n".join(lines)
