"""Pydantic models for the LLM-powered Strategy Actor.

Contains ``StrategyAction`` and ``StrategyTree`` — the structured
action models that represent the hierarchical strategy tree produced
during the ``strategize`` phase.

Forgejo: #828
"""

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, ConfigDict, Field
from ulid import ULID

__all__ = [
    "StrategyAction",
    "StrategyTree",
]


class StrategyAction(BaseModel):
    """A single action node in the hierarchical strategy tree.

    Each action describes a concrete implementation step with metadata
    for resource requirements, complexity, risk, and dependency links.
    """

    action_id: str = Field(
        default_factory=lambda: str(ULID()),
        description="ULID for this action node",
    )
    description: str = Field(
        ..., min_length=1, description="Concrete description of the action"
    )
    resource_requirements: list[str] = Field(
        default_factory=list,
        description="Resources needed for this action",
    )
    estimated_complexity: Literal["low", "medium", "high"] = Field(
        default="medium",
        description="Estimated complexity: low, medium, or high",
    )
    risk_score: float = Field(
        default=0.3,
        ge=0.0,
        le=1.0,
        description="Risk score from 0.0 (safe) to 1.0 (risky)",
    )
    depends_on: list[str] = Field(
        default_factory=list,
        description="action_ids this action depends on",
    )
    parent_id: str | None = Field(
        default=None,
        description="Parent action ID for tree hierarchy",
    )
    parent_step_explicit: bool = Field(
        default=False,
        description="If True, parent_id came from an explicit parent_step field "
        "in the LLM response (indicating hierarchical subplan). If False, it was "
        "inferred from the dependency graph.",
    )
    parallel_group: str | None = Field(
        default=None,
        description="Group key for parallel execution; steps with the same "
        "parallel_group value can be executed concurrently",
    )
    sequence: int = Field(default=0, ge=0, description="Order in the tree")

    model_config = ConfigDict(str_strip_whitespace=True, validate_assignment=True)


class StrategyTree(BaseModel):
    """Hierarchical strategy tree produced by the Strategy Actor.

    Contains the root action and all child actions, plus a validated
    dependency graph with no cycles.
    """

    root_id: str = Field(..., description="ULID of the root action")
    actions: list[StrategyAction] = Field(
        default_factory=list, description="All actions in the tree"
    )
    dependency_edges: list[tuple[str, str]] = Field(
        default_factory=list,
        description="Directed edges (from_id, to_id) in the dependency graph",
    )

    model_config = ConfigDict(str_strip_whitespace=True, validate_assignment=True)
