import os import uuid from datetime import datetime, timezone from typing import List from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status from sqlmodel import Session, select from app.config import UPLOAD_DIR from app.database import get_session from app.models.garden import Garden, GardenCell, GardenImage, Measurement router = APIRouter(tags=["jardins"]) def _save_garden_photo(data: bytes) -> str: try: from PIL import Image import io img = Image.open(io.BytesIO(data)).convert("RGB") img.thumbnail((1800, 1800)) name = f"garden_{uuid.uuid4()}.webp" path = os.path.join(UPLOAD_DIR, name) img.save(path, "WEBP", quality=88) return name except Exception: name = f"garden_{uuid.uuid4()}.bin" path = os.path.join(UPLOAD_DIR, name) with open(path, "wb") as f: f.write(data) return name @router.get("/gardens", response_model=List[Garden]) def list_gardens(session: Session = Depends(get_session)): return session.exec(select(Garden)).all() @router.post("/gardens", response_model=Garden, status_code=status.HTTP_201_CREATED) def create_garden(garden: Garden, session: Session = Depends(get_session)): session.add(garden) session.commit() session.refresh(garden) return garden @router.get("/gardens/{id}", response_model=Garden) def get_garden(id: int, session: Session = Depends(get_session)): g = session.get(Garden, id) if not g: raise HTTPException(status_code=404, detail="Jardin introuvable") return g @router.post("/gardens/{id}/photo", response_model=Garden) async def upload_garden_photo( id: int, file: UploadFile = File(...), session: Session = Depends(get_session), ): g = session.get(Garden, id) if not g: raise HTTPException(status_code=404, detail="Jardin introuvable") content_type = file.content_type or "" if not content_type.startswith("image/"): raise HTTPException(status_code=400, detail="Le fichier doit ĂȘtre une image") os.makedirs(UPLOAD_DIR, exist_ok=True) data = await file.read() filename = _save_garden_photo(data) g.photo_parcelle = f"/uploads/{filename}" g.updated_at = datetime.now(timezone.utc) session.add(g) session.commit() session.refresh(g) return g @router.put("/gardens/{id}", response_model=Garden) def update_garden(id: int, data: Garden, session: Session = Depends(get_session)): g = session.get(Garden, id) if not g: raise HTTPException(status_code=404, detail="Jardin introuvable") for k, v in data.model_dump(exclude_unset=True, exclude={"id", "created_at"}).items(): setattr(g, k, v) g.updated_at = datetime.now(timezone.utc) session.add(g) session.commit() session.refresh(g) return g @router.delete("/gardens/{id}", status_code=status.HTTP_204_NO_CONTENT) def delete_garden(id: int, session: Session = Depends(get_session)): g = session.get(Garden, id) if not g: raise HTTPException(status_code=404, detail="Jardin introuvable") session.delete(g) session.commit() @router.get("/gardens/{id}/cells", response_model=List[GardenCell]) def list_cells(id: int, session: Session = Depends(get_session)): return session.exec(select(GardenCell).where(GardenCell.garden_id == id)).all() @router.post("/gardens/{id}/cells", response_model=GardenCell, status_code=status.HTTP_201_CREATED) def create_cell(id: int, cell: GardenCell, session: Session = Depends(get_session)): cell.garden_id = id session.add(cell) session.commit() session.refresh(cell) return cell @router.put("/gardens/{id}/cells/{cell_id}", response_model=GardenCell) def update_cell(id: int, cell_id: int, data: GardenCell, session: Session = Depends(get_session)): c = session.get(GardenCell, cell_id) if not c or c.garden_id != id: raise HTTPException(status_code=404, detail="Case introuvable") for k, v in data.model_dump(exclude_unset=True, exclude={"id", "garden_id"}).items(): setattr(c, k, v) session.add(c) session.commit() session.refresh(c) return c @router.get("/gardens/{id}/measurements", response_model=List[Measurement]) def list_measurements(id: int, session: Session = Depends(get_session)): return session.exec(select(Measurement).where(Measurement.garden_id == id)).all() @router.post("/gardens/{id}/measurements", response_model=Measurement, status_code=status.HTTP_201_CREATED) def create_measurement(id: int, m: Measurement, session: Session = Depends(get_session)): m.garden_id = id session.add(m) session.commit() session.refresh(m) return m