"""Agent-role MCP tool permissions for Agent Loop mode."""

from __future__ import annotations

from enum import StrEnum

from src.plugins.mcp.interfaces import MCPTool


class AgentRole(StrEnum):
    OPENCLAW = "openclaw"
    NEMOTRON = "nemotron"
    HERMES = "hermes"
    ELEPHANT_ALPHA = "elephant_alpha"


_WRITE_TOOL_MARKERS = (
    "apply",
    "create",
    "delete",
    "patch",
    "restart",
    "rollout",
    "scale",
    "undo",
    "write",
    "commit",
    "notify",
    "send",
)

_WRITE_TOOL_NAMES = {
    "execute_sql",
    "exec_sql",
    "run_sql",
    "raw_sql",
    "ssh_exec",
    "ssh_execute",
    "shell",
    "run_command",
}

_K8S_READ_TOOL_MARKERS = (
    "describe",
    "events",
    "get",
    "hpa",
    "logs",
    "node",
    "status",
    "watch",
)


def is_read_only_tool(tool: MCPTool) -> bool:
    """Return whether a tool is considered side-effect free."""

    name = tool.name.lower()
    if name in _WRITE_TOOL_NAMES:
        return False
    if any(marker in name for marker in _WRITE_TOOL_MARKERS):
        return False
    return True


def is_tool_allowed(tool: MCPTool, agent_role: str) -> bool:
    """Check whether an agent role may receive a specific MCP tool."""

    role = _normalize_role(agent_role)
    server = tool.server_name.lower()
    name = tool.name.lower()

    if role == AgentRole.OPENCLAW:
        return True

    if role == AgentRole.NEMOTRON:
        if server in {"prometheus", "grafana", "signoz"}:
            return True
        if server == "kubernetes":
            return is_read_only_tool(tool) and any(marker in name for marker in _K8S_READ_TOOL_MARKERS)
        return False

    if role == AgentRole.HERMES:
        if server in {"database", "prometheus", "filesystem", "rag"}:
            return is_read_only_tool(tool) or server == "database"
        return False

    if role == AgentRole.ELEPHANT_ALPHA:
        return is_read_only_tool(tool)

    return False


def filter_tools_for_agent(tools: list[MCPTool], agent_role: str) -> list[MCPTool]:
    """Return only the tools allowed for an agent role."""

    return [tool for tool in tools if is_tool_allowed(tool, agent_role)]


def _normalize_role(agent_role: str) -> AgentRole:
    try:
        return AgentRole(agent_role)
    except ValueError:
        return AgentRole.ELEPHANT_ALPHA
