"""
Burrow adapter for CrewAI.

Provides task-level and tool-level guards that scan messages with Burrow.

Usage:
    from burrow import BurrowGuard
    from burrow.integrations.crewai import create_burrow_tool_hook

    guard = BurrowGuard(client_id="...", client_secret="...")
    create_burrow_tool_hook(guard)  # Registers globally
"""

from __future__ import annotations

import logging
from typing import Any

from burrow import BurrowGuard, ScanResult

__all__ = [
    "BurrowBlockedError",
    "create_burrow_task_guard",
    "create_burrow_tool_hook",
]

logger = logging.getLogger("burrow.integrations.crewai")


class BurrowBlockedError(Exception):
    """Raised when Burrow blocks a CrewAI message."""

    def __init__(self, result: ScanResult, agent_role: str = ""):
        self.result = result
        self.agent_role = agent_role
        super().__init__(
            f"Burrow blocked message from agent '{agent_role}': "
            f"{result.category} ({result.confidence:.0%} confidence)"
        )


def create_burrow_task_guard(
    guard: BurrowGuard,
    block_on_warn: bool = False,
):
    """
    Create a guard function that scans CrewAI task descriptions and contexts.

    Use this to scan task inputs before execution:

        guard_fn = create_burrow_task_guard(guard)
        for task in crew.tasks:
            guard_fn(task.description, agent_role=task.agent.role)

    Args:
        guard: BurrowGuard instance.
        block_on_warn: If True, also block on "warn" verdicts.

    Returns:
        A callable that scans text and raises on injection.
    """

    def guard_fn(
        text: str,
        agent_role: str = "",
        content_type: str = "user_prompt",
    ) -> ScanResult:
        result = guard.scan(
            text,
            content_type=content_type,
            agent=f"crewai:{agent_role}" if agent_role else "crewai",
        )
        if result.is_blocked or (block_on_warn and result.is_warning):
            raise BurrowBlockedError(result, agent_role)
        return result

    return guard_fn


def create_burrow_tool_hook(
    guard: BurrowGuard,
    block_on_warn: bool = False,
):
    """
    Register a global CrewAI before-tool-call hook that scans with Burrow.

    Uses CrewAI's native ``register_before_tool_call_hook`` so that every
    tool call across all crews in the process is scanned. The hook
    automatically extracts the calling agent's role for per-agent identity.

    Args:
        guard: BurrowGuard instance.
        block_on_warn: If True, also block on "warn" verdicts.

    Returns:
        The hook function (already registered globally).
    """
    try:
        from crewai.hooks import register_before_tool_call_hook
    except ImportError:
        try:
            from crewai.hooks.tool_hooks import register_before_tool_call_hook
        except ImportError as exc:
            raise ImportError(
                "crewai is required for the CrewAI adapter. "
                "Install it with: pip install burrow-sdk[crewai]"
            ) from exc

    def burrow_tool_hook(context: Any) -> bool:
        """Burrow before-tool-call hook for CrewAI.

        Returns False to block tool execution when injection is detected.
        """
        tool_name = getattr(context, "tool_name", None) or "unknown"
        tool_args = getattr(context, "tool_input", None) or getattr(context, "arguments", None)

        text = ""
        if isinstance(tool_args, dict):
            text = " ".join(
                str(v)
                for v in tool_args.values()
                if isinstance(v, (str, int, float)) and str(v).strip()
            )
            if not text:
                import json

                text = json.dumps(tool_args)
        elif isinstance(tool_args, str):
            text = tool_args

        text = text.strip()
        if not text:
            return True

        agent_role = ""
        agent_obj = getattr(context, "agent", None)
        if agent_obj is not None:
            agent_role = getattr(agent_obj, "role", "")

        agent_label = f"crewai:{agent_role}" if agent_role else "crewai"

        result = guard.scan(
            text,
            content_type="tool_call",
            agent=agent_label,
            tool_name=tool_name,
        )

        if result.is_blocked or (block_on_warn and result.is_warning):
            logger.warning(
                "Burrow blocked tool call %s from agent '%s': %s (%.0f%% confidence)",
                tool_name,
                agent_role,
                result.category,
                result.confidence * 100,
            )
            return False

        return True

    register_before_tool_call_hook(burrow_tool_hook)
    return burrow_tool_hook
