from typing import Annotated, Literal

from langchain.agents import AgentState
from langgraph.managed import RemainingSteps
from pydantic import BaseModel, Field
from typing_extensions import TypedDict


class AgentBuilderPlan(BaseModel):
    steps: list[str] = Field(description="The steps of the agent.")


class AgentBuilderCode(BaseModel):
    code: str = Field(description="The Python code for the agent.")


class AgentBuilderMeta(BaseModel):
    name: str = Field(description="Concise, title-cased agent name (3-6 words).")
    description: str = Field(description="Short, one-sentence description (<= 140 chars).")
    long_description: str = Field(description="Comprehensive markdown explanation/README.")


class AgentBuilderPatch(BaseModel):
    patch: str = Field(
        description=("OpenAI-style patch text wrapped between '*** Begin Patch' and '*** End Patch' fences.")
    )


class Todo(TypedDict):
    """A single todo item with content and status."""

    content: str
    """The content/description of the todo item."""

    status: Literal["pending", "in_progress", "completed"]
    """The current status of the todo item."""


def _enqueue(left: list, right: list) -> list:
    """Treat left as a FIFO queue, append new items from right (preserve order),
    keep items unique, and cap total size to 20 (drop oldest items)."""

    queue = left + right
    return list(set(queue))


class CodeActState(AgentState):
    """State for CodeAct agent."""

    context: str
    """Base64-encoded cloudpickle string containing the execution context with available tools and variables."""
    agent_builder_mode: str | None
    """State for the agent builder agent."""
    selected_tool_ids: Annotated[list[str], _enqueue]
    """Queue for tools exported from registry"""
    plan: list[str] | None
    """Plan for the agent builder agent."""
    agent_name: str | None
    """Generated agent name after confirmation."""
    agent_description: str | None
    """Generated short description after confirmation."""
    final_instructions: str | None
    """Final instructions for the agent."""
    default_tool_defs: list[str] | None
    """Default tool definitions."""
    template_id: str | None
    """Template ID for the agent, if selected"""
    agent_id: str | None
    """Agent ID for the agent, if selected. Takes priority over template_id."""
    remaining_steps: RemainingSteps
    """Remaining steps for the agent until hitting recursion limit"""
