"""Packaging generation API routes.""" from __future__ import annotations from datetime import datetime from typing import Any, Literal from uuid import uuid4 from fastapi import APIRouter, HTTPException, Query from fastapi.responses import Response from pydantic import BaseModel, Field from app.packaging.export import svg_to_pdf_bytes, svg_to_png_bytes from app.packaging.generator import FOODLINKK_BRAND, generate_packaging router = APIRouter(prefix="/packaging", tags=["packaging"]) _PROJECTS: dict[str, dict[str, Any]] = {} class PackagingSpec(BaseModel): type: Literal["folding_box", "wrap", "round_label"] width_mm: float = Field(default=120, gt=0, le=4000) height_mm: float = Field(default=80, gt=0, le=4000) depth_mm: float = Field(default=40, ge=0, le=4000) elements: dict[str, bool] = Field(default_factory=dict) brand: dict[str, str] = Field(default_factory=dict) barcode_value: str | None = Field(default=None, max_length=64) @router.post("/generate") def packaging_generate(spec: PackagingSpec) -> dict[str, Any]: spec_data = spec.model_dump() if not spec_data["brand"]: spec_data["brand"] = dict(FOODLINKK_BRAND) svg = generate_packaging(spec_data) project_id = uuid4().hex now = datetime.utcnow().isoformat() + "Z" _PROJECTS[project_id] = { "id": project_id, "created_at": now, "spec": spec_data, "svg": svg, } return {"id": project_id, "created_at": now, "svg": svg, "spec": spec_data} @router.get("/projects") def packaging_projects(limit: int = Query(default=30, ge=1, le=200)) -> dict[str, Any]: items = sorted(_PROJECTS.values(), key=lambda x: x["created_at"], reverse=True)[:limit] return { "items": [{"id": p["id"], "created_at": p["created_at"], "spec": p["spec"]} for p in items], "count": len(items), } @router.get("/download/{project_id}") def packaging_download(project_id: str, format: str = Query(default="svg", pattern="^(svg|png|pdf)$")): project = _PROJECTS.get(project_id) if not project: raise HTTPException(status_code=404, detail="Packaging project not found") svg = project["svg"] filename = f"foodlinkk-packaging-{project_id[:8]}.{format}" if format == "svg": return Response( content=svg.encode("utf-8"), media_type="image/svg+xml", headers={"Content-Disposition": f'attachment; filename="{filename}"'}, ) if format == "png": return Response( content=svg_to_png_bytes(svg), media_type="image/png", headers={"Content-Disposition": f'attachment; filename="{filename}"'}, ) return Response( content=svg_to_pdf_bytes(svg), media_type="application/pdf", headers={"Content-Disposition": f'attachment; filename="{filename}"'}, )