"""Obol interceptor for CrewAI.

Patches Agent execution to capture all task and tool executions.
Also installs LangChain interceptor since CrewAI uses LangChain tools.

Usage:
    from obol.interceptors import crewai
    crewai.install()

    # Then use CrewAI normally - all agent actions are logged
"""
import functools
from obol.interceptors._base import send_event, _content_hash

_installed = False
_original_execute_task = None
_original_kickoff = None


def _traced_execute_task(original):
    """Create a traced version of Agent.execute_task."""
    @functools.wraps(original)
    def wrapper(self, task, context=None, tools=None):
        agent_role = getattr(self, "role", self.__class__.__name__)
        task_desc = getattr(task, "description", str(task))[:500] if task else None

        # Log task start
        send_event(
            platform="crewai",
            action=f"Agent.{agent_role}.execute_task",
            target=task_desc,
            result="pending",
            metadata={
                "agent_role": agent_role,
                "agent_goal": getattr(self, "goal", "")[:200] if hasattr(self, "goal") else None,
                "tool_count": len(tools) if tools else 0,
            }
        )

        try:
            result = original(self, task, context=context, tools=tools)

            # Log task success
            send_event(
                platform="crewai",
                action=f"Agent.{agent_role}.execute_task",
                target=task_desc,
                result="success",
                metadata={
                    "agent_role": agent_role,
                    "output_size": len(str(result)) if result else 0,
                }
            )

            return result

        except Exception as e:
            # Log task error
            send_event(
                platform="crewai",
                action=f"Agent.{agent_role}.execute_task",
                target=task_desc,
                result="error",
                metadata={
                    "agent_role": agent_role,
                    "error_type": type(e).__name__,
                    "error_message": str(e)[:500],
                }
            )
            raise

    return wrapper


def _traced_kickoff(original):
    """Create a traced version of Crew.kickoff."""
    @functools.wraps(original)
    def wrapper(self, inputs=None):
        crew_name = getattr(self, "name", "unnamed_crew")

        # Log crew start
        send_event(
            platform="crewai",
            action="Crew.kickoff",
            target=crew_name,
            result="pending",
            metadata={
                "crew_name": crew_name,
                "agent_count": len(self.agents) if hasattr(self, "agents") else 0,
                "task_count": len(self.tasks) if hasattr(self, "tasks") else 0,
                "has_inputs": inputs is not None,
            }
        )

        try:
            result = original(self, inputs=inputs)

            # Log crew success
            send_event(
                platform="crewai",
                action="Crew.kickoff",
                target=crew_name,
                result="success",
                metadata={
                    "crew_name": crew_name,
                    "output_size": len(str(result)) if result else 0,
                }
            )

            return result

        except Exception as e:
            # Log crew error
            send_event(
                platform="crewai",
                action="Crew.kickoff",
                target=crew_name,
                result="error",
                metadata={
                    "crew_name": crew_name,
                    "error_type": type(e).__name__,
                    "error_message": str(e)[:500],
                }
            )
            raise

    return wrapper


def install():
    """Install the CrewAI interceptor.

    Patches Agent.execute_task() and Crew.kickoff() to capture all executions.
    Also installs LangChain interceptor for tool-level capture.
    Safe to call multiple times.
    """
    global _installed, _original_execute_task, _original_kickoff

    if _installed:
        return

    # Also install LangChain interceptor (CrewAI uses LangChain tools)
    try:
        from obol.interceptors import langchain
        langchain.install()
    except Exception:
        pass

    try:
        from crewai import Agent, Crew
    except ImportError:
        return  # CrewAI not installed

    # Patch Agent.execute_task
    if hasattr(Agent, "execute_task"):
        _original_execute_task = Agent.execute_task
        Agent.execute_task = _traced_execute_task(_original_execute_task)

    # Patch Crew.kickoff
    if hasattr(Crew, "kickoff"):
        _original_kickoff = Crew.kickoff
        Crew.kickoff = _traced_kickoff(_original_kickoff)

    _installed = True


def uninstall():
    """Remove the CrewAI interceptor."""
    global _installed, _original_execute_task, _original_kickoff

    if not _installed:
        return

    try:
        from crewai import Agent, Crew
    except ImportError:
        return

    if _original_execute_task:
        Agent.execute_task = _original_execute_task
    if _original_kickoff:
        Crew.kickoff = _original_kickoff

    _installed = False


def is_installed():
    """Check if the interceptor is currently installed."""
    return _installed
