from fastapi import APIRouter, HTTPException, Depends
from typing import Dict, Any
import logging

from ...api.models.laser import (
    LaserParameters,
    LaserStatus,
    LaserStartResponse,
    LaserStopResponse,
    ManualLaserParameters,
    ManualLaserStartResponse
)
from ...core.laser.laser_controller import LaserController
from ...core import singletons

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1/laser", tags=["laser"])


def get_laser_controller():
    """Dependency to get laser controller instance from singletons"""
    return singletons.laser_controller_instance


@router.post("/start", response_model=LaserStartResponse)
async def start_laser_cycle(
    parameters: LaserParameters,
    controller: LaserController = Depends(get_laser_controller)
) -> LaserStartResponse:
    """
    Start laser control cycle with specified parameters.

    This endpoint accepts laser control parameters and starts the measurement cycle.
    All parameters are validated and logged.
    """
    try:
        logger.info("Received request to start laser cycle")

        # Validate that only one scan mode is enabled at a time
        # (Manual mode = all disabled, Scan mode = one enabled)
        enabled_modes = sum([
            parameters.enable_t1,
            parameters.enable_t2,
            parameters.enable_c1,
            parameters.enable_c2
        ])
        if enabled_modes > 1:
            raise HTTPException(
                status_code=400,
                detail="Можно включить только один режим сканирования одновременно"
            )

        # Start the cycle
        result = controller.start_cycle(parameters)

        if not result["success"]:
            raise HTTPException(status_code=500, detail=result["message"])

        return LaserStartResponse(
            success=True,
            message=result["message"],
            parameters=parameters
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Unexpected error starting laser cycle: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Внутренняя ошибка сервера: {str(e)}")


@router.post("/start-manual", response_model=ManualLaserStartResponse)
async def start_manual_laser_control(
    parameters: ManualLaserParameters,
    controller: LaserController = Depends(get_laser_controller)
) -> ManualLaserStartResponse:
    """
    Start manual laser control with simplified parameters (t1, t2, i1, i2).

    This endpoint is designed for direct manual control without scan modes.
    It accepts only 4 parameters and immediately applies them to the device.

    Args:
        parameters: Manual control parameters with t1, t2, i1, i2

    Returns:
        ManualLaserStartResponse with success status and message
    """
    try:
        logger.info("Received request to start manual laser control")
        logger.info(f"Parameters: T1={parameters.t1}°C, T2={parameters.t2}°C, I1={parameters.i1}mA, I2={parameters.i2}mA")

        # Call the simplified manual control method
        result = controller.start_manual_direct(
            t1=parameters.t1,
            t2=parameters.t2,
            i1=parameters.i1,
            i2=parameters.i2
        )

        if not result["success"]:
            raise HTTPException(status_code=500, detail=result["message"])

        return ManualLaserStartResponse(
            success=True,
            message=result["message"],
            parameters=parameters
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Unexpected error starting manual laser control: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Внутренняя ошибка сервера: {str(e)}")


@router.post("/stop", response_model=LaserStopResponse)
async def stop_laser_cycle(
    controller: LaserController = Depends(get_laser_controller)
) -> LaserStopResponse:
    """
    Stop the current laser control cycle.
    """
    try:
        logger.info("Received request to stop laser cycle")

        result = controller.stop_cycle()

        if not result["success"]:
            raise HTTPException(status_code=500, detail=result["message"])

        return LaserStopResponse(
            success=True,
            message=result["message"]
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Unexpected error stopping laser cycle: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Внутренняя ошибка сервера: {str(e)}")


@router.get("/status", response_model=LaserStatus)
async def get_laser_status(
    controller: LaserController = Depends(get_laser_controller)
) -> LaserStatus:
    """
    Get current laser status including temperature, current, and voltage readings.
    """
    try:
        status = controller.get_status()
        return status

    except Exception as e:
        logger.error(f"Error getting laser status: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Ошибка получения статуса: {str(e)}")


@router.post("/connect")
async def connect_laser(
    port: str = None,
    controller: LaserController = Depends(get_laser_controller)
) -> Dict[str, Any]:
    """
    Connect to laser control hardware on specified port.

    Args:
        port: Serial port (e.g., '/dev/ttyUSB0'). If not specified, auto-detect.
    """
    try:
        logger.info(f"Received request to connect to laser hardware on port: {port or 'auto-detect'}")

        # If already connected, disconnect first
        if controller.is_connected:
            logger.info("Already connected, disconnecting first...")
            controller.disconnect()

        result = controller.connect(port)

        if not result["success"]:
            raise HTTPException(status_code=500, detail=result["message"])

        return result

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error connecting to laser: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Ошибка подключения: {str(e)}")


@router.post("/disconnect")
async def disconnect_laser(
    controller: LaserController = Depends(get_laser_controller)
) -> Dict[str, Any]:
    """
    Disconnect from laser control hardware.
    """
    try:
        logger.info("Received request to disconnect from laser hardware")

        result = controller.disconnect()

        if not result["success"]:
            raise HTTPException(status_code=500, detail=result["message"])

        return result

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error disconnecting from laser: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Ошибка отключения: {str(e)}")
