from __future__ import annotations

import asyncio
from typing import Any

from fastapi import APIRouter, HTTPException, WebSocket, WebSocketDisconnect

from k1link.device_plugins.xgrids_k1.facade import (
    ACTION_DISCOVERY_SCAN,
    ACTION_NETWORK_PROVISION,
    ACTION_STATE_READ,
    ACTION_STREAM_START_LIVE,
    ACTION_STREAM_START_REPLAY,
    ACTION_STREAM_STOP,
    ACTION_VIEWER_SETTINGS_UPDATE,
    BleScanRequest,
    ConnectRequest,
    LiveRequest,
    ReplayRequest,
    ViewerSettingsRequest,
)
from k1link.web.plugin_runtime import (
    DevicePluginRuntimeTransport,
    PluginExecutionError,
    invoke_device_plugin_runtime,
)


def build_xgrids_k1_legacy_router(runtime: DevicePluginRuntimeTransport) -> APIRouter:
    """Temporary flat API kept for scripts created before the plugin boundary."""

    router = APIRouter(include_in_schema=True)

    @router.get("/api/state", deprecated=True)
    async def get_state() -> dict[str, Any]:
        return await invoke_device_plugin_runtime(runtime, ACTION_STATE_READ, {})

    @router.post("/api/ble/scan", deprecated=True)
    async def scan_ble(request: BleScanRequest) -> dict[str, Any]:
        try:
            return await invoke_device_plugin_runtime(
                runtime,
                ACTION_DISCOVERY_SCAN,
                request.model_dump(),
            )
        except (PluginExecutionError, ValueError) as exc:
            raise HTTPException(status_code=502, detail=f"Ошибка поиска BLE: {exc}") from exc

    @router.post("/api/connect", deprecated=True)
    async def connect(request: ConnectRequest) -> dict[str, Any]:
        try:
            return await invoke_device_plugin_runtime(
                runtime,
                ACTION_NETWORK_PROVISION,
                request.model_dump(),
            )
        except (PluginExecutionError, ValueError) as exc:
            raise HTTPException(
                status_code=502,
                detail=f"Ошибка подключения устройства к Wi-Fi: {exc}",
            ) from exc

    @router.post("/api/session/live", deprecated=True)
    async def start_live(request: LiveRequest) -> dict[str, Any]:
        try:
            return await invoke_device_plugin_runtime(
                runtime,
                ACTION_STREAM_START_LIVE,
                request.model_dump(),
            )
        except (PluginExecutionError, ValueError) as exc:
            raise HTTPException(status_code=400, detail=str(exc)) from exc

    @router.post("/api/session/replay", deprecated=True)
    async def start_replay(request: ReplayRequest) -> dict[str, Any]:
        try:
            return await invoke_device_plugin_runtime(
                runtime,
                ACTION_STREAM_START_REPLAY,
                request.model_dump(),
            )
        except (PluginExecutionError, ValueError) as exc:
            raise HTTPException(status_code=400, detail=str(exc)) from exc

    @router.post("/api/session/stop", deprecated=True)
    async def stop_session() -> dict[str, Any]:
        return await invoke_device_plugin_runtime(runtime, ACTION_STREAM_STOP, {})

    @router.post("/api/viewer/settings", deprecated=True)
    async def update_viewer_settings(request: ViewerSettingsRequest) -> dict[str, Any]:
        return await invoke_device_plugin_runtime(
            runtime,
            ACTION_VIEWER_SETTINGS_UPDATE,
            request.model_dump(),
        )

    @router.websocket("/api/events")
    async def events(websocket: WebSocket) -> None:
        await websocket.accept()
        try:
            while True:
                await websocket.send_json(
                    {
                        "state": await invoke_device_plugin_runtime(
                            runtime,
                            ACTION_STATE_READ,
                            {},
                        )
                    }
                )
                await asyncio.sleep(0.5)
        except WebSocketDisconnect:
            return

    return router
