"""Gradient routes: CRUD for reusable gradient definitions."""

from fastapi import APIRouter, Depends, HTTPException

from wled_controller.api.auth import AuthRequired
from wled_controller.api.dependencies import (
    fire_entity_event,
    get_color_strip_store,
    get_gradient_store,
)
from wled_controller.api.schemas.gradients import (
    GradientCreate,
    GradientListResponse,
    GradientResponse,
    GradientUpdate,
)
from wled_controller.storage.gradient import Gradient
from wled_controller.storage.gradient_store import GradientStore
from wled_controller.storage.color_strip_store import ColorStripStore
from wled_controller.storage.base_store import EntityNotFoundError
from wled_controller.utils import get_logger

logger = get_logger(__name__)

router = APIRouter()


def _to_response(gradient: Gradient) -> GradientResponse:
    return GradientResponse(
        id=gradient.id,
        name=gradient.name,
        stops=[{"position": s["position"], "color": s["color"]} for s in gradient.stops],
        is_builtin=gradient.is_builtin,
        description=gradient.description,
        tags=gradient.tags,
        created_at=gradient.created_at,
        updated_at=gradient.updated_at,
    )


@router.get("/api/v1/gradients", response_model=GradientListResponse, tags=["Gradients"])
async def list_gradients(
    _auth: AuthRequired,
    store: GradientStore = Depends(get_gradient_store),
):
    """List all gradients (built-in + user-created)."""
    gradients = store.get_all_gradients()
    return GradientListResponse(
        gradients=[_to_response(g) for g in gradients],
        count=len(gradients),
    )


@router.post("/api/v1/gradients", response_model=GradientResponse, status_code=201, tags=["Gradients"])
async def create_gradient(
    data: GradientCreate,
    _auth: AuthRequired,
    store: GradientStore = Depends(get_gradient_store),
):
    """Create a new user-defined gradient."""
    try:
        gradient = store.create_gradient(
            name=data.name,
            stops=[s.model_dump() for s in data.stops],
            description=data.description,
            tags=data.tags,
        )
        fire_entity_event("gradient", "created", gradient.id)
        return _to_response(gradient)
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/api/v1/gradients/{gradient_id}", response_model=GradientResponse, tags=["Gradients"])
async def get_gradient(
    gradient_id: str,
    _auth: AuthRequired,
    store: GradientStore = Depends(get_gradient_store),
):
    """Get a gradient by ID."""
    try:
        gradient = store.get_gradient(gradient_id)
        return _to_response(gradient)
    except (ValueError, EntityNotFoundError) as e:
        raise HTTPException(status_code=404, detail=str(e))


@router.put("/api/v1/gradients/{gradient_id}", response_model=GradientResponse, tags=["Gradients"])
async def update_gradient(
    gradient_id: str,
    data: GradientUpdate,
    _auth: AuthRequired,
    store: GradientStore = Depends(get_gradient_store),
):
    """Update a gradient (built-in gradients are read-only)."""
    try:
        stops = [s.model_dump() for s in data.stops] if data.stops is not None else None
        gradient = store.update_gradient(
            gradient_id=gradient_id,
            name=data.name,
            stops=stops,
            description=data.description,
            tags=data.tags,
        )
        fire_entity_event("gradient", "updated", gradient_id)
        return _to_response(gradient)
    except (ValueError, EntityNotFoundError) as e:
        status = 404 if "not found" in str(e).lower() else 400
        raise HTTPException(status_code=status, detail=str(e))


@router.post("/api/v1/gradients/{gradient_id}/clone", response_model=GradientResponse, status_code=201, tags=["Gradients"])
async def clone_gradient(
    gradient_id: str,
    _auth: AuthRequired,
    store: GradientStore = Depends(get_gradient_store),
):
    """Clone a gradient (useful for customizing built-in gradients)."""
    try:
        original = store.get_gradient(gradient_id)
        clone = store.create_gradient(
            name=f"{original.name} (copy)",
            stops=original.stops,
            description=original.description,
            tags=original.tags,
        )
        fire_entity_event("gradient", "created", clone.id)
        return _to_response(clone)
    except (ValueError, EntityNotFoundError) as e:
        status = 404 if "not found" in str(e).lower() else 400
        raise HTTPException(status_code=status, detail=str(e))


@router.delete("/api/v1/gradients/{gradient_id}", status_code=204, tags=["Gradients"])
async def delete_gradient(
    gradient_id: str,
    _auth: AuthRequired,
    store: GradientStore = Depends(get_gradient_store),
    css_store: ColorStripStore = Depends(get_color_strip_store),
):
    """Delete a gradient (fails if built-in or referenced by sources)."""
    try:
        # Check references
        for source in css_store.get_all_sources():
            if getattr(source, "gradient_id", None) == gradient_id:
                raise ValueError(
                    f"Cannot delete: referenced by color strip source '{source.name}'"
                )
        store.delete_gradient(gradient_id)
        fire_entity_event("gradient", "deleted", gradient_id)
    except (ValueError, EntityNotFoundError) as e:
        status = 404 if "not found" in str(e).lower() else 400
        raise HTTPException(status_code=status, detail=str(e))
