"""Execute an agent turn — the core orchestration primitive.

Used by:
- HandoffNode (via ctx.services.runtime)
- StageNode (via tool registry as agent.turn)
- Direct tool invocation by agents
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from core.pathways.models.tool import ToolOutput

if TYPE_CHECKING:
    from core.pathways.context import Context


async def run(
    agent_id: str,
    message: str,
    thread_id: str | None = None,
    pathway: str | None = None,
    context: Context | None = None,
) -> ToolOutput:
    """Execute a single turn with a registered agent.

    Args:
        agent_id: ID of the agent to execute (e.g., "system.researcher")
        message: The message/goal to send to the agent
        thread_id: Optional thread ID for conversation continuity
        pathway: Optional pathway override (react, plan_execute, etc.)
        context: Execution context (injected by framework)
    """
    if not agent_id:
        return ToolOutput(success=False, error="agent_id is required")
    if not message:
        return ToolOutput(success=False, error="message is required")

    if not context:
        return ToolOutput(success=False, error="Context not available")

    runtime = context.services.runtime
    if not runtime:
        return ToolOutput(
            success=False,
            error="Runtime not available — cannot run agent turns",
        )

    effective_thread_id = thread_id or context.run.thread_id or "tool_turn"

    try:
        result = await runtime.turn(
            agent_id=agent_id,
            message=message,
            thread_id=effective_thread_id,
            pathway_override=pathway,
        )

        return ToolOutput(
            success=result.success,
            data={
                "agent_id": agent_id,
                "response": result.response,
                "steps_taken": result.steps_taken,
                "cost_usd": 0.0,
            },
            error=result.error if not result.success else None,
        )

    except Exception as e:
        return ToolOutput(
            success=False,
            error=f"Agent turn failed for '{agent_id}': {e}",
        )
