"""The core diagnosis MCP tool.

``diagnose_execution`` answers the project's central question: which action
died, why, and what was missing upstream. It delegates the 9-step flow to
``services.diagnose`` and returns the verdict-first dict. The result never
contains the raw bot JSON — only the parsed action surface and a disk path
to the local snapshot (Phase 7).

``diagnose_execution`` is classified READ-ONLY in ``policies/write_guards``
(it reads execution history, it does not run bots), so it needs no confirm gate.

A ``LocalSnapshotStore`` is constructed per call from the server config —
construction is cheap (path computation only, no I/O). The store persists
each diagnosed execution locally so it survives Control Room's 90-day
retention cutoff.
"""

from __future__ import annotations

from pydantic import BaseModel, Field

from ..auth.auth_manager import AuthManager
from ..services import diagnose as diagnose_service
from ..utils.config import ServerConfig
from ..utils.registry import register_tool
from ..utils.snapshot_store import LocalSnapshotStore


class DiagnoseExecutionParams(BaseModel):
    execution_id: str = Field(description="Failed execution id (NOT deploymentId) to diagnose.")
    refresh: bool = Field(
        default=False,
        description="Re-diagnose against Control Room, ignoring the local snapshot.",
    )


@register_tool(
    "diagnose_execution",
    params=DiagnoseExecutionParams,
    description="Diagnose a failed run: which action, why, what's missing.",
)
def diagnose_execution(
    config: ServerConfig, auth_manager: AuthManager, params: DiagnoseExecutionParams
) -> dict:
    snapshot_store = LocalSnapshotStore(
        control_room_url=config.control_room_url,
        username=config.auth.username,
    )
    return diagnose_service.diagnose(
        auth_manager,
        params.execution_id,
        snapshot_store=snapshot_store,
        refresh=params.refresh,
    )
