"""Tool filtering based on side-effect annotations.

Provides schema-level enforcement of tool access by execution role.
Workers receive only side-effect-free (read-only) tools, while the
judge has access to all tools.

The `x-side-effects` annotation follows established CS terminology:
- "none": Pure read, idempotent, no state changes
- "local": Modifies local/session state only
- "external": Modifies external systems

Deny-by-default: Unannotated tools are blocked for workers.
"""

from __future__ import annotations

from collections.abc import Mapping, Sequence
from enum import Enum
from typing import Any


class SideEffects(Enum):
    """Tool side-effect classification.

    Based on functional programming concepts:
    - NONE: Pure function, no side effects, safe for parallel execution
    - LOCAL: Effects contained to local/session scope
    - EXTERNAL: Effects visible to external systems
    - UNKNOWN: No annotation, treated conservatively
    """

    NONE = "none"
    LOCAL = "local"
    EXTERNAL = "external"
    UNKNOWN = "unknown"


def get_side_effects(tool: Mapping[str, Any]) -> SideEffects:
    """Extract side-effect annotation from a tool definition.

    Checks both top-level and function-level annotations for flexibility:
    - Top-level: {"type": "function", "x-side-effects": "none", ...}
    - Function-level: {"type": "function", "function": {"x-side-effects": "none", ...}}

    Args:
        tool: Tool definition in OpenAI function-calling format.

    Returns:
        SideEffects enum value. Returns UNKNOWN for unannotated tools.
    """
    # Check top-level annotation first
    effects = tool.get("x-side-effects")

    if effects is None:
        # Fall back to function-level annotation
        function = tool.get("function")
        if isinstance(function, Mapping):
            effects = function.get("x-side-effects")

    if effects == "none":
        return SideEffects.NONE
    if effects == "local":
        return SideEffects.LOCAL
    if effects == "external":
        return SideEffects.EXTERNAL

    return SideEffects.UNKNOWN


__all__ = [
    "SideEffects",
    "get_side_effects",
]
