"""MCP handoff tool — writes a HandoffReference at pilot context boundary."""

from __future__ import annotations

import logging

from fastmcp.exceptions import ToolError
from fastmcp.tools import tool

from mcp_vm_blackbox.coordination_db import get_db

_LOG = logging.getLogger(__name__)


@tool
async def vm_handoff_create(
    job_id: str,
    vm_name: str,
    todo_position: str,
    next_intended_action: str,
    key_observations: str,
    full_log_path: str,
    last_completed_step_id: int | None = None,
) -> dict:
    """Write a HandoffReference for the active pilot before pausing.

    Call this BEFORE vm_job_pause when approaching context exhaustion.
    The incoming pilot reads this record at startup to resume efficiently
    without reconstructing state from the full step log.

    Args:
        job_id: Active job identifier.
        vm_name: Target VM name.
        todo_position: The TODO item or step label the pilot was working on
            at handoff time (e.g. "milestone-3 / step-7: Install JDK").
        next_intended_action: The specific action the pilot intended to take
            next (e.g. "Run vm_powershell to verify JDK installation").
        key_observations: Critical facts the incoming pilot must know:
            current screen state, environment facts, blocker details.
            Free-text; multi-line accepted.
        full_log_path: Path to the evidence/log directory for this job.
            Default if unknown: ".mcp-vm-blackbox/evidence/{vm_name}/{job_id}/".
        last_completed_step_id: Integer step_id of the last successfully
            completed step. When omitted, resolved automatically from the
            job_steps table. Pass explicitly only when the resolved value
            would be wrong (e.g., after a step was rolled back).

    Returns:
        Dict with ``handoff_id`` (UUID string), ``created_at`` (ISO-8601),
        ``job_id``, and ``vm_name``.

    Raises:
        ToolError: If job_id does not exist for vm_name, or on DB failure.
    """
    db = await get_db()
    try:
        handoff_id, created_at = await db.create_handoff(
            job_id=job_id,
            vm_name=vm_name,
            todo_position=todo_position,
            next_intended_action=next_intended_action,
            key_observations=key_observations,
            full_log_path=full_log_path,
            last_completed_step_id=last_completed_step_id,
        )
    except ValueError as exc:
        raise ToolError(f"Job {job_id!r} not found on VM {vm_name!r}") from exc
    except Exception as exc:
        raise ToolError(f"Failed to create handoff for job {job_id!r}: {exc}") from exc
    return {"handoff_id": handoff_id, "created_at": created_at, "job_id": job_id, "vm_name": vm_name}


@tool
async def vm_handoff_read(job_id: str, vm_name: str) -> dict:
    """Read the latest HandoffReference for a paused job.

    Call this at startup when resuming a paused job discovered via
    vm_job_list. Returns the outgoing pilot's compact working-state
    summary so you can resume at the exact TODO position without
    replaying the full step log.

    Args:
        job_id: Job identifier of the paused job.
        vm_name: Target VM name.

    Returns:
        Dict with all HandoffReference fields when found, or a
        structured not-found signal when no handoff exists.

    Raises:
        ToolError: On unexpected database failure.
    """
    db = await get_db()
    try:
        row = await db.get_latest_handoff(job_id, vm_name)
    except Exception as exc:
        raise ToolError(f"Failed to read handoff for job {job_id!r} on VM {vm_name!r}: {exc}") from exc
    if row is None:
        return {"found": False, "job_id": job_id, "vm_name": vm_name}
    return {"found": True, **row}
