from typing import Any

from fastapi import APIRouter, HTTPException, Query

import vna_system.core.singletons as singletons
from vna_system.core.logging.logger import get_component_logger

router = APIRouter(prefix="/api/v1", tags=["acquisition"])
logger = get_component_logger(__file__)


@router.get("/acquisition/status")
async def get_acquisition_status() -> dict[str, Any]:
    """
    Return current acquisition status.

    Response
    --------
    {
        "running": bool,
        "paused": bool,
        "continuous_mode": bool,
        "sweep_count": int
    }
    """
    acquisition = singletons.vna_data_acquisition_instance
    if acquisition is None:
        logger.error("Acquisition singleton is not initialized")
        raise HTTPException(status_code=500, detail="Сбор данных не инициализирован")

    return {
        "running": acquisition.is_running,
        "paused": acquisition.is_paused,
        "continuous_mode": acquisition.is_continuous_mode,
        "sweep_count": acquisition.sweep_buffer.current_sweep_number,
    }


@router.post("/acquisition/start")
async def start_acquisition() -> dict[str, Any]:
    """
    Start data acquisition in continuous mode (resumes if paused).
    """
    try:
        acquisition = singletons.vna_data_acquisition_instance
        if acquisition is None:
            logger.error("Acquisition singleton is not initialized")
            raise HTTPException(status_code=500, detail="Сбор данных не инициализирован")

        if not acquisition.is_running:
            acquisition.start()
            logger.info("Acquisition thread started via API")

        acquisition.set_continuous_mode(True)
        return {"success": True, "message": "Сбор данных запущен"}
    except HTTPException:
        raise
    except Exception as exc:  # noqa: BLE001
        logger.error("Failed to start acquisition")
        raise HTTPException(status_code=500, detail=str(exc))


@router.post("/acquisition/stop")
async def stop_acquisition() -> dict[str, Any]:
    """
    Pause data acquisition (thread remains alive for fast resume).
    """
    try:
        acquisition = singletons.vna_data_acquisition_instance
        if acquisition is None:
            logger.error("Acquisition singleton is not initialized")
            raise HTTPException(status_code=500, detail="Сбор данных не инициализирован")

        if not acquisition.is_running:
            return {"success": True, "message": "Сбор данных уже остановлен"}

        acquisition.pause()
        logger.info("Acquisition paused via API")
        return {"success": True, "message": "Сбор данных приостановлен"}
    except HTTPException:
        raise
    except Exception as exc:  # noqa: BLE001
        logger.error("Failed to stop acquisition")
        raise HTTPException(status_code=500, detail=str(exc))


@router.post("/acquisition/single-sweep")
async def trigger_single_sweep() -> dict[str, Any]:
    """
    Trigger a single sweep.
    Automatically starts acquisition if needed and switches to single-sweep mode.
    """
    try:
        acquisition = singletons.vna_data_acquisition_instance
        if acquisition is None:
            logger.error("Acquisition singleton is not initialized")
            raise HTTPException(status_code=500, detail="Сбор данных не инициализирован")

        if not acquisition.is_running:
            acquisition.start()
            logger.info("Acquisition thread started (single-sweep request)")

        acquisition.trigger_single_sweep()
        return {"success": True, "message": "Одиночный свип запущен"}
    except HTTPException:
        raise
    except Exception as exc:  # noqa: BLE001
        logger.error("Failed to trigger single sweep")
        raise HTTPException(status_code=500, detail=str(exc))


@router.get("/acquisition/latest-sweep")
async def get_latest_sweep(
    limit: int = Query(10, ge=1, le=1000, description="Максимальное число точек в ответе"),
) -> dict[str, Any]:
    """
    Return the latest sweep metadata and a limited subset of points.

    Query Params
    ------------
    limit : int
        Number of points to include from the start of the sweep (default 10, max 1000).
    """
    try:
        acquisition = singletons.vna_data_acquisition_instance
        if acquisition is None:
            logger.error("Acquisition singleton is not initialized")
            raise HTTPException(status_code=500, detail="Сбор данных не инициализирован")

        latest_sweep = acquisition.sweep_buffer.get_latest_sweep()
        if not latest_sweep:
            return {"sweep": None, "message": "Данные свипа недоступны"}

        points = latest_sweep.points[:limit]
        return {
            "sweep": {
                "sweep_number": latest_sweep.sweep_number,
                "timestamp": latest_sweep.timestamp,
                "total_points": latest_sweep.total_points,
                "points": points,
            },
            "message": f"Последний свип №{latest_sweep.sweep_number}, точек: {latest_sweep.total_points}",
        }
    except HTTPException:
        raise
    except Exception as exc:  # noqa: BLE001
        logger.error("Failed to fetch latest sweep")
        raise HTTPException(status_code=500, detail=str(exc))
