"""LoopNode — iteration until condition."""

from __future__ import annotations

from typing import TYPE_CHECKING, Literal

from pydantic import Field

from core.pathways.expressions import safe_eval
from core.pathways.models.io import NodeInputs, NodeOutputs
from core.pathways.nodes.base import NodeBase
from core.pathways.nodes.models import LoopOutput

if TYPE_CHECKING:
    from core.pathways.context import Context


class LoopNode(NodeBase):
    """Loop iteration — executes body nodes until condition is met.

    Attributes
    ----------
    condition : str
        Expression to continue loop (while this is true).
    body : list[str]
        List of node IDs to execute in each iteration.
    max_iterations : int
        Safety limit.
    collect_results : bool
        Whether to collect all iteration results.
    """

    type: Literal["loop"] = "loop"
    condition: str
    body: list[str] = Field(default_factory=list)
    max_iterations: int = 10
    collect_results: bool = True

    async def compute(self, inputs: NodeInputs, _ctx: Context) -> NodeOutputs:
        """Evaluate whether to continue the loop."""
        template_data = inputs.to_dict()
        iteration = inputs.get("_iteration", 0)

        if iteration >= self.max_iterations:
            loop_output = LoopOutput(
                should_continue=False,
                iteration=iteration,
                reason="max_iterations_reached",
            )
            return NodeOutputs(
                output=loop_output.model_dump(),
                continue_loop=False,
            )

        formatted_condition = self._format_template(self.condition, template_data)
        should_continue = bool(safe_eval(formatted_condition, env=template_data))

        loop_output = LoopOutput(
            should_continue=should_continue,
            iteration=iteration,
            body_nodes=self.body,
        )
        return NodeOutputs(
            output=loop_output.model_dump(),
            continue_loop=should_continue,
        )


__all__ = ["LoopNode"]
