"""The structured action the agent emits each turn (build plan Section 6.1).

The model is asked to reply with a JSON object:

    {"thought": "...", "action": "tool_name" | "final", "args": {...}}

Malformed output raises :class:`ActionParseError`; the runner retries a bounded
number of times, then fails safe.
"""

from __future__ import annotations

import json

from pydantic import BaseModel, Field, ValidationError


class ActionParseError(ValueError):
    """Raised when the model's output is not a valid action object."""


class AgentAction(BaseModel):
    thought: str = ""
    action: str = Field(min_length=1)
    args: dict = Field(default_factory=dict)

    @property
    def is_final(self) -> bool:
        return self.action == "final"


def _strip_code_fences(text: str) -> str:
    text = text.strip()
    if text.startswith("```"):
        # Drop the opening fence (optionally ```json) and the closing fence.
        lines = text.splitlines()
        if lines and lines[0].startswith("```"):
            lines = lines[1:]
        if lines and lines[-1].strip() == "```":
            lines = lines[:-1]
        text = "\n".join(lines).strip()
    return text


def parse_action(content: str) -> AgentAction:
    cleaned = _strip_code_fences(content)
    try:
        data = json.loads(cleaned)
    except json.JSONDecodeError as exc:
        raise ActionParseError(f"response was not valid JSON: {exc}") from exc
    if not isinstance(data, dict):
        raise ActionParseError("response JSON must be an object")
    try:
        return AgentAction.model_validate(data)
    except ValidationError as exc:
        raise ActionParseError(f"response did not match the action schema: {exc}") from exc
