from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_current_user
from app.db.database import get_db
from app.db.models import CanvasState, Design, Edge, Node
from app.schemas.designs import DesignCreate, DesignResponse, DesignUpdate

router = APIRouter()


@router.get("", response_model=list[DesignResponse])
async def list_designs(
    db: AsyncSession = Depends(get_db),
    _: str = Depends(get_current_user),
) -> list[DesignResponse]:
    designs = (await db.execute(select(Design).order_by(Design.created_at))).scalars().all()
    return [DesignResponse.model_validate(d) for d in designs]


@router.post("", response_model=DesignResponse, status_code=201)
async def create_design(
    body: DesignCreate,
    db: AsyncSession = Depends(get_db),
    _: str = Depends(get_current_user),
) -> DesignResponse:
    design = Design(name=body.name, design_type=body.design_type, icon=body.icon)
    db.add(design)
    await db.flush()
    # Create empty canvas state for the new design
    db.add(CanvasState(design_id=design.id))
    await db.commit()
    await db.refresh(design)
    return DesignResponse.model_validate(design)


@router.put("/{design_id}", response_model=DesignResponse)
async def update_design(
    design_id: str,
    body: DesignUpdate,
    db: AsyncSession = Depends(get_db),
    _: str = Depends(get_current_user),
) -> DesignResponse:
    design = await db.get(Design, design_id)
    if not design:
        raise HTTPException(404, "Design not found")
    if body.name is not None:
        design.name = body.name
    if body.icon is not None:
        design.icon = body.icon
    await db.commit()
    await db.refresh(design)
    return DesignResponse.model_validate(design)


@router.delete("/{design_id}", status_code=204)
async def delete_design(
    design_id: str,
    db: AsyncSession = Depends(get_db),
    _: str = Depends(get_current_user),
) -> None:
    design = await db.get(Design, design_id)
    if not design:
        raise HTTPException(404, "Design not found")
    # Count remaining designs — prevent deleting the last one
    count = (await db.execute(select(Design))).scalars().all()
    if len(count) <= 1:
        raise HTTPException(400, "Cannot delete the only design")
    # Delete associated canvas state, edges, nodes
    cs = await db.get(CanvasState, design_id)
    if cs:
        await db.delete(cs)
    edges = (await db.execute(select(Edge).where(Edge.design_id == design_id))).scalars().all()
    for e in edges:
        await db.delete(e)
    nodes = (await db.execute(select(Node).where(Node.design_id == design_id))).scalars().all()
    for n in nodes:
        await db.delete(n)
    await db.delete(design)
    await db.commit()
