"""
Workflow orchestration for EvenAge.

Supports two modes:
- coordinator: a coordinator agent orchestrates worker agents via delegation
- sequential: agents run in sequence, passing results along the chain
"""

from __future__ import annotations

from typing import Any, Optional


class Workflow:
    def __init__(self, name: str, description: str | None = None, mode: str | None = None) -> None:
        self.name = name
        self.description = description or ""
        self.mode = (mode or "sequential").lower()

        # Coordinator mode fields
        self._coordinator = None
        self._workers: list[Any] = []

        # Sequential mode fields
        self._sequence: list[Any] = []

        # Configuration storage
        self._config: dict[str, Any] = {}

    # Coordinator mode API
    def add_coordinator(self, agent: Any) -> None:
        self._coordinator = agent

    def add_worker(self, agent: Any) -> None:
        self._workers.append(agent)

    # Sequential mode API
    def add_node(self, agent: Any, next: Optional[str] = None) -> None:  # noqa: A002 - allow 'next' per template API
        # We keep the order of calls as the sequence. 'next' is accepted for API compatibility.
        self._sequence.append(agent)

    # Shared configuration
    def configure(self, **kwargs: Any) -> None:
        # Store but do not enforce specific backends here; AgentRunner/Env handles those.
        self._config.update(kwargs)

    async def run(self, inputs: dict[str, Any] | None = None) -> dict[str, Any]:
        """Execute the workflow with provided inputs.

        For coordinator mode, forwards the task to the coordinator agent.
        For sequential mode, runs each agent in order, piping previous output under 'input'.
        """
        payload: dict[str, Any] = inputs or {}

        if self.mode == "coordinator":
            if not self._coordinator:
                raise RuntimeError("Coordinator mode selected but no coordinator added.")
            # Coordinator is expected to delegate to workers via bus; we pass initial payload.
            # Agent.handle expects a dict payload and returns a structured dict.
            result = await self._coordinator.handle(payload)
            return result

        # Sequential mode
        if not self._sequence:
            raise RuntimeError("Sequential workflow has no nodes.")

        last_result: Any = payload
        for agent in self._sequence:
            step_payload = last_result if isinstance(last_result, dict) else {"input": last_result}
            out = await agent.handle(step_payload)
            # out is expected to be a dict with key 'result' for Agent.handle
            if isinstance(out, dict) and "result" in out:
                last_result = out["result"]
            else:
                last_result = out

        # Return final structured response similar to Agent.handle output
        return {
            "status": "success",
            "result": last_result,
            "workflow": self.name,
            "mode": self.mode,
        }
