"""Space management endpoints.""" from typing import Annotated from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.core.deps import get_current_admin, get_current_user, get_db from app.models.space import Space from app.models.user import User from app.schemas.space import SpaceCreate, SpaceResponse, SpaceStatusUpdate, SpaceUpdate from app.services.audit_service import log_action router = APIRouter(prefix="/spaces", tags=["spaces"]) admin_router = APIRouter(prefix="/admin/spaces", tags=["admin"]) @router.get("", response_model=list[SpaceResponse]) def list_spaces( db: Annotated[Session, Depends(get_db)], current_user: Annotated[User, Depends(get_current_user)], ) -> list[Space]: """ Get list of spaces. - Users see only active spaces - Admins see all spaces (active + inactive) """ query = db.query(Space) # Filter by active status for non-admin users if current_user.role != "admin": query = query.filter(Space.is_active == True) # noqa: E712 spaces = query.order_by(Space.name).all() return spaces @admin_router.post("", response_model=SpaceResponse, status_code=status.HTTP_201_CREATED) def create_space( space_data: SpaceCreate, db: Annotated[Session, Depends(get_db)], current_admin: Annotated[User, Depends(get_current_admin)], ) -> Space: """ Create a new space (admin only). - name: required, non-empty - type: "sala" or "birou" - capacity: must be > 0 - description: optional """ # Check if space with same name exists existing = db.query(Space).filter(Space.name == space_data.name).first() if existing: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Space with name '{space_data.name}' already exists", ) space = Space( name=space_data.name, type=space_data.type, capacity=space_data.capacity, description=space_data.description, is_active=True, ) db.add(space) db.commit() db.refresh(space) # Log the action log_action( db=db, action="space_created", user_id=current_admin.id, target_type="space", target_id=space.id, details={"name": space.name, "type": space.type, "capacity": space.capacity} ) return space @admin_router.put("/{space_id}", response_model=SpaceResponse) def update_space( space_id: int, space_data: SpaceUpdate, db: Annotated[Session, Depends(get_db)], current_admin: Annotated[User, Depends(get_current_admin)], ) -> Space: """ Update an existing space (admin only). All fields are required (full update). """ space = db.query(Space).filter(Space.id == space_id).first() if not space: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Space not found", ) # Check if new name conflicts with another space if space_data.name != space.name: existing = db.query(Space).filter(Space.name == space_data.name).first() if existing: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Space with name '{space_data.name}' already exists", ) # Track what changed updated_fields = [] if space.name != space_data.name: updated_fields.append("name") if space.type != space_data.type: updated_fields.append("type") if space.capacity != space_data.capacity: updated_fields.append("capacity") if space.description != space_data.description: updated_fields.append("description") setattr(space, "name", space_data.name) setattr(space, "type", space_data.type) setattr(space, "capacity", space_data.capacity) setattr(space, "description", space_data.description) db.commit() db.refresh(space) # Log the action log_action( db=db, action="space_updated", user_id=current_admin.id, target_type="space", target_id=space.id, details={"updated_fields": updated_fields} ) return space @admin_router.patch("/{space_id}/status", response_model=SpaceResponse) def update_space_status( space_id: int, status_data: SpaceStatusUpdate, db: Annotated[Session, Depends(get_db)], _: Annotated[User, Depends(get_current_admin)], ) -> Space: """ Activate or deactivate a space (admin only). Deactivated spaces will not appear in booking lists for users. """ space = db.query(Space).filter(Space.id == space_id).first() if not space: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Space not found", ) setattr(space, "is_active", status_data.is_active) db.commit() db.refresh(space) return space