from __future__ import annotations

from dataclasses import dataclass
from typing import Awaitable, Callable, Optional, Protocol


@dataclass(frozen=True)
class Pose2D:
    x: float
    y: float
    theta: float


@dataclass(frozen=True)
class NavUpdate:
    status: str
    progress: Optional[float] = None
    reason: Optional[str] = None
    error_code: Optional[str] = None


NavUpdateCallback = Callable[[NavUpdate], Awaitable[None]]


class NavBackend(Protocol):
    async def start(self) -> None:
        ...

    async def stop(self) -> None:
        ...

    async def navigate_to_pose(
        self,
        request_id: str,
        destination: str,
        pose: Pose2D,
        speed: str,
        on_update: NavUpdateCallback,
        frame_id: str = "map",
    ) -> None:
        """Run navigation until completion.

        Implementations should invoke `on_update` with intermediate updates.
        """

    async def cancel(self, request_id: str, reason: str = "") -> None:
        ...
