"""Handoff orchestration pattern (dynamic delegation between agents)."""

from __future__ import annotations

import logging
from dataclasses import dataclass, field
from typing import Any

from cyberbrain26.orchestration.subagent.interface import BaseSubagent
from cyberbrain26.orchestration.subagent.types import SubagentOutput

logger = logging.getLogger(__name__)


@dataclass
class HandoffTool:
    """Represents a handoff tool for dynamic agent-to-agent delegation."""

    target_agent: str
    context_summary: str
    reason: str
    unresolved: list[str] = field(default_factory=list)
    max_handoffs: int = 3  # Hard limit per AWS Cedar (depth > 5 denied)
    current_handoff_count: int = 0

    def can_handoff(self) -> bool:
        """Return True if handoff count is under the limit."""
        return self.current_handoff_count < self.max_handoffs

    def increment(self) -> None:
        """Increment the handoff count."""
        self.current_handoff_count += 1


@dataclass
class HandoffResult:
    """Result of a handoff transition."""

    target_agent: str
    context_summary: str
    handoff_reason: str
    unresolved_tasks: list[str]
    confidence: float = 1.0
    human_interaction_required: bool = False


class HandoffPattern(BaseSubagent):
    """Handoff pattern: dynamic delegation between agents.

    Implements the "handoff" pattern where agents hand control to each other
    directly rather than going through a central supervisor. Used when:
    - The optimal agent isn't known upfront
    - Task requires multi-turn interaction with user
    - Domain requirements emerge during processing

    Per Azure Architecture Center:
    - Full control transfers from one agent to another
    - Agents decide when to transfer control
    - Dynamic routing based on context analysis
    - Requires handoff counter cap to prevent infinite loops
    """

    def __init__(self, spec: Any) -> None:
        super().__init__(spec)
        self._available_agents: dict[str, Any] = {}
        self._current_handoff_count = 0
        self._max_handoffs = 3

    def register_agent(self, agent_name: str, handoff_tool: Any) -> None:
        """Register an agent that can receive handoffs."""
        self._available_agents[agent_name] = handoff_tool

    async def invoke(self, input_data: dict[str, Any]) -> SubagentOutput:
        """Execute handoff pattern: dynamically delegate to next agent.

        Args:
            input_data: Input containing task context

        Returns:
            Structured output from handoff execution
        """
        if not self._available_agents:
            return SubagentOutput(
                summary="No agents available for handoff",
                confidence=0.0,
                requires_human_review=True,
                obstacles=["No handoff targets registered"],
            )

        if not self._can_handoff():
            return SubagentOutput(
                summary="Maximum handoff depth reached",
                confidence=0.0,
                requires_human_review=True,
                obstacles=["Handoff limit exceeded; escalating to human"],
            )

        # Determine next agent based on context analysis
        target_agent, reason, context_summary = self._select_target(input_data)

        handoff_result = HandoffResult(
            target_agent=target_agent,
            context_summary=context_summary,
            handoff_reason=reason,
            unresolved_tasks=input_data.get("unresolved_tasks", []),
        )

        self._current_handoff_count += 1

        return SubagentOutput(
            summary=f"Handoff to {target_agent}: {reason}",
            confidence=handoff_result.confidence,
            requires_human_review=handoff_result.human_interaction_required,
            obstacles=[
                f"Handed off to {target_agent}",
                *(handoff_result.unresolved_tasks),
            ],
        )

    def _can_handoff(self) -> bool:
        """Return True if handoff count is under limit."""
        return self._current_handoff_count < self._max_handoffs

    def _select_target(
        self, input_data: dict[str, Any]
    ) -> tuple[str, str, str]:
        """Select next agent for handoff based on context analysis."""
        # Simple heuristic: pick first available agent
        agent_name = next(iter(self._available_agents))
        return agent_name, "Dynamic handoff selected", f"Context: {input_data.get('task', 'unknown')}"