from __future__ import annotations

from mcp.server.fastmcp import FastMCP

from ..config import DEFAULT_PROFILE
from ..errors import QingflowApiError, raise_tool_error
from ..json_types import JSONObject
from .base import ToolBase


class RoleTools(ToolBase):
    def register(self, mcp: FastMCP) -> None:
        @mcp.tool()
        def role_search(
            profile: str = DEFAULT_PROFILE,
            keyword: str = "",
            page_num: int = 1,
            page_size: int = 50,
        ) -> JSONObject:
            return self.role_search(profile=profile, keyword=keyword, page_num=page_num, page_size=page_size)

        @mcp.tool()
        def role_create(profile: str = DEFAULT_PROFILE, payload: JSONObject | None = None) -> JSONObject:
            return self.role_create(profile=profile, payload=payload or {})

        @mcp.tool(description=self._high_risk_tool_description(operation="update", target="role configuration"))
        def role_update(
            profile: str = DEFAULT_PROFILE,
            role_id: int = 0,
            payload: JSONObject | None = None,
        ) -> JSONObject:
            return self.role_update(profile=profile, role_id=role_id, payload=payload or {})

        @mcp.tool(description=self._high_risk_tool_description(operation="delete", target="roles and assignments"))
        def role_delete(profile: str = DEFAULT_PROFILE, role_ids: list[int] | None = None) -> JSONObject:
            return self.role_delete(profile=profile, role_ids=role_ids or [])

    def role_search(self, *, profile: str, keyword: str, page_num: int, page_size: int) -> JSONObject:
        if page_num <= 0 or page_size <= 0:
            raise_tool_error(QingflowApiError.config_error("page_num and page_size must be positive"))

        def runner(session_profile, context):
            result = self.backend.request(
                "GET",
                context,
                "/contact/roleByPage",
                params={"keyword": keyword, "pageNum": page_num, "pageSize": page_size},
            )
            return {
                "profile": profile,
                "ws_id": session_profile.selected_ws_id,
                "keyword": keyword,
                "page": result,
            }

        return self._run(profile, runner)

    def role_create(self, *, profile: str, payload: JSONObject) -> JSONObject:
        body = self._require_dict(payload)

        def runner(session_profile, context):
            result = self.backend.request("POST", context, "/contact/role", json_body=body)
            return {"profile": profile, "ws_id": session_profile.selected_ws_id, "result": result}

        return self._run(profile, runner)

    def role_update(self, *, profile: str, role_id: int, payload: JSONObject) -> JSONObject:
        if role_id <= 0:
            raise_tool_error(QingflowApiError.config_error("role_id must be positive"))
        body = self._require_dict(payload)

        def runner(session_profile, context):
            result = self.backend.request("POST", context, f"/contact/role/{role_id}", json_body=body)
            return self._attach_human_review_notice(
                {"profile": profile, "ws_id": session_profile.selected_ws_id, "role_id": role_id, "result": result},
                operation="update",
                target="role configuration",
            )

        return self._run(profile, runner)

    def role_delete(self, *, profile: str, role_ids: list[int]) -> JSONObject:
        if not role_ids or any(role_id <= 0 for role_id in role_ids):
            raise_tool_error(QingflowApiError.config_error("role_ids must be a non-empty array of positive integers"))

        def runner(session_profile, context):
            result = self.backend.request("DELETE", context, "/contact/role", json_body=role_ids)
            return self._attach_human_review_notice(
                {"profile": profile, "ws_id": session_profile.selected_ws_id, "role_ids": role_ids, "result": result},
                operation="delete",
                target="roles and assignments",
            )

        return self._run(profile, runner)
