from __future__ import annotations

import asyncio
from typing import Optional

from .base import NavBackend, NavUpdate, NavUpdateCallback, Pose2D


class MockNavBackend(NavBackend):
    def __init__(self) -> None:
        self._cancelled: bool = False
        self._active_request_id: Optional[str] = None

    async def start(self) -> None:
        return

    async def stop(self) -> None:
        return

    async def navigate_to_pose(
        self,
        request_id: str,
        destination: str,
        pose: Pose2D,
        speed: str,
        on_update: NavUpdateCallback,
        frame_id: str = "map",
    ) -> None:
        _ = frame_id  # Mock backend ignores frame; kept for interface compatibility.
        self._cancelled = False
        self._active_request_id = request_id

        await on_update(NavUpdate(status="accepted", progress=0.0))

        steps = 10
        for i in range(1, steps + 1):
            await asyncio.sleep(0.25)
            if self._cancelled and self._active_request_id == request_id:
                await on_update(NavUpdate(status="cancelled", progress=max(0.0, (i - 1) / steps)))
                return
            await on_update(NavUpdate(status="navigating", progress=i / steps))

        await on_update(NavUpdate(status="arrived", progress=1.0))

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