"""Calibration test endpoint for color strip sources."""

from fastapi import APIRouter, Depends, HTTPException

from ledgrab.api.auth import AuthRequired
from ledgrab.api.dependencies import get_color_strip_store, get_processor_manager
from ledgrab.api.schemas.color_strip_sources import CSSCalibrationTestRequest
from ledgrab.api.schemas.devices import CalibrationTestModeResponse
from ledgrab.core.processing.processor_manager import ProcessorManager
from ledgrab.storage.color_strip_source import (
    AdvancedPictureColorStripSource,
    PictureColorStripSource,
)
from ledgrab.storage.color_strip_store import ColorStripStore
from ledgrab.utils import get_logger

logger = get_logger(__name__)

router = APIRouter()


@router.put(
    "/api/v1/color-strip-sources/{source_id}/calibration/test",
    response_model=CalibrationTestModeResponse,
    tags=["Color Strip Sources"],
)
async def test_css_calibration(
    source_id: str,
    body: CSSCalibrationTestRequest,
    _auth: AuthRequired,
    store: ColorStripStore = Depends(get_color_strip_store),
    manager: ProcessorManager = Depends(get_processor_manager),
):
    """Temporarily light up LED edges to verify calibration.

    Pass a device_id and an edges dict with RGB colors.
    Send an empty edges dict to exit test mode.
    """
    try:
        # Validate device exists in manager
        if not manager.has_device(body.device_id):
            raise HTTPException(status_code=404, detail=f"Device {body.device_id} not found")

        # Validate edge names and colors
        valid_edges = {"top", "right", "bottom", "left"}
        for edge_name, color in body.edges.items():
            if edge_name not in valid_edges:
                raise HTTPException(
                    status_code=400,
                    detail=f"Invalid edge '{edge_name}'. Must be one of: {', '.join(sorted(valid_edges))}",
                )
            if len(color) != 3 or not all(0 <= c <= 255 for c in color):
                raise HTTPException(
                    status_code=400,
                    detail=f"Invalid color for edge '{edge_name}'. Must be [R, G, B] with values 0-255.",
                )

        # Get CSS calibration to send the right pixel pattern
        calibration = None
        if body.edges:
            try:
                source = store.get_source(source_id)
                if not isinstance(
                    source, (PictureColorStripSource, AdvancedPictureColorStripSource)
                ):
                    raise HTTPException(
                        status_code=400,
                        detail="Calibration test is only available for picture color strip sources",
                    )
                if source.calibration:
                    calibration = source.calibration
            except ValueError as e:
                raise HTTPException(status_code=404, detail=str(e))

        await manager.set_test_mode(body.device_id, body.edges, calibration)

        active_edges = list(body.edges.keys())
        logger.info(
            f"CSS calibration test mode {'activated' if active_edges else 'deactivated'} "
            f"for device {body.device_id} via CSS {source_id}: {active_edges}"
        )

        return CalibrationTestModeResponse(
            test_mode=len(active_edges) > 0,
            active_edges=active_edges,
            device_id=body.device_id,
        )

    except HTTPException:
        raise
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.error("Failed to set CSS calibration test mode: %s", e, exc_info=True)
        raise HTTPException(status_code=500, detail="Internal server error")
