""" API Routes for Image Templates. """ from typing import Optional, Dict, Any from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from pydantic import BaseModel from app.core.database import get_db from app.models.image_template import ImageTemplate router = APIRouter() class TemplateCreate(BaseModel): """Schema for creating an image template.""" name: str description: Optional[str] = None category: str template_type: str = "general" html_template: Optional[str] = None template_file: Optional[str] = None variables: list design_config: Optional[Dict[str, Any]] = None output_sizes: Optional[Dict[str, Any]] = None class TemplateUpdate(BaseModel): """Schema for updating a template.""" name: Optional[str] = None description: Optional[str] = None category: Optional[str] = None template_type: Optional[str] = None html_template: Optional[str] = None variables: Optional[list] = None design_config: Optional[Dict[str, Any]] = None output_sizes: Optional[Dict[str, Any]] = None is_active: Optional[bool] = None class PreviewRequest(BaseModel): """Schema for previewing a template.""" template_id: Optional[int] = None html_template: Optional[str] = None variables: Dict[str, str] output_size: Optional[Dict[str, int]] = None @router.get("/") async def list_templates( category: Optional[str] = None, template_type: Optional[str] = None, active_only: bool = True, limit: int = Query(50, ge=1, le=200), db: Session = Depends(get_db) ): """ List all image templates. - **category**: Filter by category (tip, producto, servicio, etc.) - **template_type**: Filter by type (tip_card, product_card, quote, etc.) - **active_only**: Only show active templates """ query = db.query(ImageTemplate) if category: query = query.filter(ImageTemplate.category == category) if template_type: query = query.filter(ImageTemplate.template_type == template_type) if active_only: query = query.filter(ImageTemplate.is_active == True) templates = query.order_by(ImageTemplate.name).limit(limit).all() return { "templates": [t.to_dict() for t in templates], "count": len(templates) } @router.get("/{template_id}") async def get_template( template_id: int, db: Session = Depends(get_db) ): """ Get a specific template with full details. """ template = db.query(ImageTemplate).filter(ImageTemplate.id == template_id).first() if not template: raise HTTPException(status_code=404, detail="Template not found") result = template.to_dict() # Include full HTML template if template.html_template: result["full_html_template"] = template.html_template return result @router.post("/") async def create_template( template_data: TemplateCreate, db: Session = Depends(get_db) ): """ Create a new image template. Templates can be defined with: - **html_template**: Inline HTML/CSS template - **template_file**: Path to a template file Variables are placeholders like: ["title", "content", "accent_color"] """ if not template_data.html_template and not template_data.template_file: raise HTTPException( status_code=400, detail="Either html_template or template_file is required" ) template = ImageTemplate( name=template_data.name, description=template_data.description, category=template_data.category, template_type=template_data.template_type, html_template=template_data.html_template, template_file=template_data.template_file, variables=template_data.variables, design_config=template_data.design_config, output_sizes=template_data.output_sizes, is_active=True ) db.add(template) db.commit() db.refresh(template) return { "message": "Template created successfully", "template": template.to_dict() } @router.put("/{template_id}") async def update_template( template_id: int, template_data: TemplateUpdate, db: Session = Depends(get_db) ): """ Update an existing template. """ template = db.query(ImageTemplate).filter(ImageTemplate.id == template_id).first() if not template: raise HTTPException(status_code=404, detail="Template not found") update_data = template_data.dict(exclude_unset=True) for field, value in update_data.items(): if value is not None: setattr(template, field, value) db.commit() db.refresh(template) return { "message": "Template updated successfully", "template": template.to_dict() } @router.delete("/{template_id}") async def delete_template( template_id: int, db: Session = Depends(get_db) ): """ Delete a template. """ template = db.query(ImageTemplate).filter(ImageTemplate.id == template_id).first() if not template: raise HTTPException(status_code=404, detail="Template not found") db.delete(template) db.commit() return {"message": "Template deleted successfully"} @router.post("/preview") async def preview_template( preview_data: PreviewRequest, db: Session = Depends(get_db) ): """ Generate a preview of a template with variables. You can either provide: - **template_id**: To use an existing template - **html_template**: To preview custom HTML The preview returns the rendered HTML (image generation requires separate processing). """ html_template = preview_data.html_template if preview_data.template_id: template = db.query(ImageTemplate).filter( ImageTemplate.id == preview_data.template_id ).first() if not template: raise HTTPException(status_code=404, detail="Template not found") html_template = template.html_template if not html_template: raise HTTPException( status_code=400, detail="No HTML template available" ) # Simple variable substitution rendered_html = html_template for var_name, var_value in preview_data.variables.items(): rendered_html = rendered_html.replace(f"{{{{{var_name}}}}}", str(var_value)) # Get output size output_size = preview_data.output_size or {"width": 1080, "height": 1080} return { "rendered_html": rendered_html, "output_size": output_size, "variables_used": list(preview_data.variables.keys()) } @router.get("/categories/list") async def list_categories( db: Session = Depends(get_db) ): """ Get list of available template categories. """ from sqlalchemy import distinct categories = db.query(distinct(ImageTemplate.category)).filter( ImageTemplate.is_active == True ).all() return { "categories": [c[0] for c in categories if c[0]] } @router.get("/types/list") async def list_template_types( db: Session = Depends(get_db) ): """ Get list of available template types. """ from sqlalchemy import distinct types = db.query(distinct(ImageTemplate.template_type)).filter( ImageTemplate.is_active == True ).all() return { "types": [t[0] for t in types if t[0]] }