"""AdvancePhaseTool — LLM-driven phase transition (G6, KTD6).

Registered alongside other tools when ReActEngine has a phase_policy set.
The LLM calls this tool to signal "I'm done planning, move to building".
"""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from agentkit.tools.base import Tool

if TYPE_CHECKING:
    from agentkit.core.react import ReActEngine

logger = logging.getLogger(__name__)


class AdvancePhaseTool(Tool):
    """Tool that advances the ReActEngine's current phase.

    KTD6: LLM-driven phase transitions. Auto-advance is opt-in via
    ``plan_exec.auto_advance_after_steps``; this tool is the manual path.

    The tool holds a weak reference to the engine (via bound method
    ``engine.advance_phase``) — registered only when phase_policy is set.
    """

    def __init__(
        self,
        engine: "ReActEngine",
        name: str = "advance_phase",
        description: str | None = None,
        version: str = "1.0.0",
        tags: list[str] | None = None,
    ):
        super().__init__(
            name=name,
            description=description
            or (
                "Advance the PLAN_EXEC phase state machine to the next phase "
                "(Planning → Building → Verification → Delivery). Call this "
                "when you have finished the current phase's work and are ready "
                "to move on. Returns the new phase name or an error if you "
                "are already at the final (Delivery) phase."
            ),
            input_schema={
                "type": "object",
                "properties": {},
                "additionalProperties": False,
            },
            version=version,
            tags=tags or ["phase", "control"],
        )
        self._engine = engine

    async def execute(self, **kwargs) -> dict[str, object]:
        # Capture previous phase before transition (engine is single-threaded per request).
        previous = self._engine.current_phase
        new_phase = self._engine.advance_phase()
        if new_phase is None:
            # Either no policy set, or already at DELIVERY.
            current = self._engine.current_phase
            if current is None:
                return {
                    "is_error": True,
                    "error": "no_phase_policy",
                    "message": "No phase policy is set — advance_phase is a no-op.",
                }
            return {
                "is_error": True,
                "error": "already_at_final_phase",
                "message": (f"Already at final phase ({current.value}). Cannot advance further."),
                "current_phase": current.value,
            }
        return {
            "is_error": False,
            "previous_phase": previous.value if previous else "",
            "current_phase": new_phase.value,
            "message": f"Phase advanced to {new_phase.value}.",
        }
