"""Contact folder routes — CRUD, move contacts, reorder.""" from __future__ import annotations import uuid from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.core.db import get_db from app.deps import require_permission from app.schemas.contact_folder import ( ContactFolderCreate, ContactFolderUpdate, MoveContactRequest, ) from app.services import contact_folder_service router = APIRouter(prefix="/api/v1/contact-folders", tags=["contact-folders"]) @router.get("") async def list_folders( db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("contacts:read")), ): """List all contact folders for the current user.""" tenant_id = uuid.UUID(current_user["tenant_id"]) user_id = uuid.UUID(current_user["user_id"]) return await contact_folder_service.list_folders(db, tenant_id, user_id) @router.post("", status_code=status.HTTP_201_CREATED) async def create_folder( body: ContactFolderCreate, db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("contacts:write")), ): """Create a new contact folder.""" tenant_id = uuid.UUID(current_user["tenant_id"]) user_id = uuid.UUID(current_user["user_id"]) return await contact_folder_service.create_folder( db, tenant_id, user_id, body.name, body.parent_id ) @router.put("/{folder_id}") async def update_folder( folder_id: str, body: ContactFolderUpdate, db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("contacts:write")), ): """Update a contact folder (name, parent, sort_order).""" tenant_id = uuid.UUID(current_user["tenant_id"]) user_id = uuid.UUID(current_user["user_id"]) data = body.model_dump(exclude_none=True) try: return await contact_folder_service.update_folder( db, tenant_id, user_id, folder_id, data ) except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) @router.delete("/{folder_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_folder( folder_id: str, db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("contacts:write")), ): """Delete a contact folder. Contacts are unassigned.""" tenant_id = uuid.UUID(current_user["tenant_id"]) user_id = uuid.UUID(current_user["user_id"]) try: await contact_folder_service.delete_folder(db, tenant_id, user_id, folder_id) except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) @router.put("/{folder_id}/reorder") async def reorder_folders( folder_id: str, body: list[dict], db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("contacts:write")), ): """Batch reorder folders. Body: [{id, sort_order, parent_id?}, ...].""" tenant_id = uuid.UUID(current_user["tenant_id"]) user_id = uuid.UUID(current_user["user_id"]) await contact_folder_service.reorder_folders(db, tenant_id, user_id, body) return {"ok": True} @router.put("/contacts/{contact_id}/move") async def move_contact( contact_id: str, body: MoveContactRequest, db: AsyncSession = Depends(get_db), current_user: dict = Depends(require_permission("contacts:write")), ): """Move a contact to a folder (or unassign with folder_id=null).""" tenant_id = uuid.UUID(current_user["tenant_id"]) try: return await contact_folder_service.move_contact( db, tenant_id, contact_id, body.folder_id ) except ValueError as e: raise HTTPException(status_code=404, detail=str(e))