import os import tempfile import uuid from typing import Optional from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile from fastapi.responses import FileResponse from api.middlewares.rate_limit_middleware import limiter from models.sql.user import UserModel from services.template_codegen_service import generate_pptx_from_template from utils.auth_dependencies import get_current_user from fastapi import Request TEMPLATE_CODEGEN_ROUTER = APIRouter(prefix="/template-codegen", tags=["Template CodeGen"]) @TEMPLATE_CODEGEN_ROUTER.post("/generate") @limiter.limit("3/minute") async def generate_from_template( request: Request, presentation_id: str = Form(...), template_file: UploadFile = File(...), custom_prompt: Optional[str] = Form(None), _current_user: UserModel = Depends(get_current_user), ): """ Generate a populated PPTX from a branded template file and existing presentation content. Accepts: multipart/form-data with presentation_id, template_file (.pptx), custom_prompt (optional) Returns: PPTX file download """ # Validate file type filename = template_file.filename or "" if not filename.lower().endswith(".pptx"): raise HTTPException(status_code=400, detail="Template file must be a .pptx file") # Save uploaded template to temp tmp_dir = os.environ.get("TEMP_DIRECTORY", tempfile.gettempdir()) template_path = os.path.join(tmp_dir, f"template_{uuid.uuid4().hex}.pptx") output_path = os.path.join(tmp_dir, f"output_{uuid.uuid4().hex}.pptx") try: content = await template_file.read() with open(template_path, "wb") as f: f.write(content) result = await generate_pptx_from_template( template_path=template_path, presentation_id=presentation_id, custom_prompt=custom_prompt or "", output_path=output_path, ) return FileResponse( path=result["output_path"], media_type="application/vnd.openxmlformats-officedocument.presentationml.presentation", filename="presentation-from-template.pptx", background=None, ) except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) except RuntimeError as e: raise HTTPException(status_code=500, detail=str(e)) finally: # Clean up template file try: os.unlink(template_path) except Exception: pass