"""
Defines the Pydantic models for task plan "definitions".

These models represent the exact structure that an LLM is expected to generate.
They serve as a blueprint or definition for a plan, which the system then uses
to construct the final, internal TaskPlan object. They are used for input
validation and for programmatically generating a JSON schema for tool descriptions.
"""
from typing import List
from pydantic import BaseModel, Field, field_validator

class TaskDefinitionSchema(BaseModel):
    """A Pydantic model representing a single task as defined by an LLM."""
    task_name: str = Field(..., description="A short, unique, descriptive name for this task within the plan (e.g., 'setup_project', 'implement_scraper'). Used for defining dependencies.")
    assignee_name: str = Field(..., description="The name of the agent or sub-team assigned to this task.")
    description: str = Field(..., description="A detailed description of the task.")
    dependencies: List[str] = Field(
        default_factory=list,
        description="A list of 'task_name' values for tasks that must be completed first."
    )

class TaskPlanDefinitionSchema(BaseModel):
    """A Pydantic model representing a full task plan as generated by an LLM."""
    overall_goal: str = Field(..., description="The high-level objective of the entire plan.")
    tasks: List[TaskDefinitionSchema] = Field(..., description="The list of tasks that make up this plan.")

    @field_validator('tasks')
    def task_names_must_be_unique(cls, tasks: List[TaskDefinitionSchema]) -> List[TaskDefinitionSchema]:
        """Ensures that the LLM-provided task_names are unique within the plan."""
        seen_names = set()
        for task in tasks:
            if task.task_name in seen_names:
                raise ValueError(f"Duplicate task_name '{task.task_name}' found in task list. Each task_name must be unique.")
            seen_names.add(task.task_name)
        return tasks
