"""Tool 调用策略：人格白名单、权限和副作用边界。"""

from dataclasses import dataclass
from typing import Literal

from zbt.core.errors import AppError


@dataclass(frozen=True)
class ToolPolicy:
    personas: tuple[str, ...]
    effect: Literal["read", "draft"]
    required_permissions: tuple[str, ...] = ()


class HarnessPolicyEngine:
    def can_use(
        self,
        *,
        persona: str,
        allowed_by_persona: tuple[str, ...],
        tool_name: str,
        policy: ToolPolicy,
        permissions: tuple[str, ...],
    ) -> bool:
        if tool_name not in allowed_by_persona or persona not in policy.personas:
            return False
        if persona == "operation" and policy.effect != "read":
            return False
        return not (
            policy.required_permissions
            and "*" not in permissions
            and not set(policy.required_permissions).intersection(permissions)
        )

    def authorize(
        self,
        *,
        persona: str,
        allowed_by_persona: tuple[str, ...],
        tool_name: str,
        policy: ToolPolicy,
        permissions: tuple[str, ...],
    ) -> None:
        if tool_name not in allowed_by_persona or persona not in policy.personas:
            raise AppError(
                "AGENT_TOOL_NOT_ALLOWED",
                f"当前Agent人格不能使用工具：{tool_name}",
                403,
            )
        if persona == "operation" and policy.effect != "read":
            raise AppError(
                "AGENT_OPERATION_READ_ONLY",
                "运营Agent只允许执行只读工具",
                403,
            )
        if (
            policy.required_permissions
            and "*" not in permissions
            and not set(policy.required_permissions).intersection(permissions)
        ):
            raise AppError(
                "PERMISSION_DENIED",
                f"缺少工具权限：{tool_name}",
                403,
            )
