"""x402 CrewAI adapter — multi-agent payment management.

CrewAI runs multiple agents that call tools in parallel. x402 manages
a shared credit pool across all agents in a crew.

Usage:
    from x402_frameworks import x402CrewAI
    from crewai import Agent, Task, Crew

    x402 = x402CrewAI(api_key="your-key", max_budget_usd=50)

    researcher = Agent(
        role="Token Researcher",
        goal="Research crypto tokens",
        tools=[x402.wrap("token_scan", scan_func)],
    )
    # Crew runs, x402 manages payments across all agents
"""

from __future__ import annotations

import functools
import logging
from typing import Any, Callable, Optional

from .base import x402Adapter

logger = logging.getLogger("x402.crewai")


class x402CrewAI(x402Adapter):
    """CrewAI adapter — shared payment pool across all agents in a crew.

    Features:
    - Shared credit pool (all agents in a crew share a budget)
    - Per-crew budget tracking
    - Auto-suspend when budget exhausted
    - Detailed billing report per crew run
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._crew_budget: dict[str, float] = {}

    def set_crew_budget(self, crew_name: str, budget_usd: float):
        """Set a budget for a specific crew. Agents in this crew share the budget."""
        self._crew_budget[crew_name] = budget_usd

    def wrap(self, tool_name: str, tool_func: Callable) -> Callable:
        """Wrap a tool function with x402 payment for CrewAI agents.

        Unlike LangChain's decorator, this returns the wrapped function
        directly for use in CrewAI's Agent tool list.
        """
        return self.wrap_tool(tool_name)(tool_func)

    def wrap_tool(self, tool_name: str, tool_func: Optional[Callable] = None) -> Callable:
        def decorator(func: Callable) -> Callable:
            @functools.wraps(func)
            def wrapper(*args, **kwargs):
                available, price, source = self.check_available(tool_name)
                if not available:
                    invoice = self.get_invoice(tool_name)
                    from .langchain_adapter import PaymentRequiredError
                    raise PaymentRequiredError(
                        tool=tool_name,
                        price_usd=price,
                        pay_to=invoice.get("pay_to", ""),
                        chain=invoice.get("chain", "base"),
                        invoice_id=invoice.get("id", ""),
                    )
                result = func(*args, **kwargs)
                if source == "paid":
                    self.record_usage(tool_name, price)
                logger.info(f"CrewAI x402: {tool_name} = ${price:.4f}")
                return result

            return wrapper

        if tool_func is not None:
            return decorator(tool_func)
        return decorator

    def get_crew_report(self) -> dict:
        """Get billing report for the current session."""
        return {
            "total_spent": round(self._spent_this_month, 2),
            "budget_remaining": round(max(0, self.max_budget_usd - self._spent_this_month), 2),
            "tools_called": 0,  # Tracked internally
        }
