from __future__ import annotations import io from typing import Any, Dict, Literal, Optional from fastapi import FastAPI, HTTPException from fastapi.responses import HTMLResponse, RedirectResponse, StreamingResponse from pydantic import BaseModel, Field from .renderer import render_html, render_pdf_bytes app = FastAPI( title="Doc Compiler Service", version="1.0.0", description=( "Servicio de compilación que recibe JSON de documentación, " "renderiza plantillas Jinja2 y devuelve HTML o PDF." ), ) class CompileRequest(BaseModel): doc: Dict[str, Any] = Field( ..., description=( "JSON de documentación generado por la IA " "(incluyendo metadata.script_type)." ), ) job_id: Optional[str] = Field( None, description=( "Identificador opcional para el archivo " "(por ejemplo, nombre del script o job)." ), ) output: Literal["html", "pdf"] = Field( "pdf", description="Tipo de salida deseada. En estos endpoints se usa como referencia.", ) @app.get("/") def root(): """Endpoint raíz que redirige automáticamente a la documentación.""" return RedirectResponse(url="/docs") @app.get("/health") def health_check(): """Endpoint simple de healthcheck para monitoreo.""" return {"status": "ok"} @app.post("/compile/html") def compile_html(req: CompileRequest): """ Recibe JSON y devuelve el HTML renderizado (útil para depuración o previsualización). """ if not req.doc: raise HTTPException(status_code=400, detail="Campo 'doc' es obligatorio") try: html = render_html(req.doc) except Exception as exc: raise HTTPException( status_code=500, detail=f"Error al renderizar HTML: {exc}", ) return HTMLResponse(content=html) @app.post("/compile/pdf") def compile_pdf(req: CompileRequest): """ Recibe JSON y devuelve el PDF compilado (WeasyPrint). """ if not req.doc: raise HTTPException(status_code=400, detail="Campo 'doc' es obligatorio") job_id = req.job_id or "document" try: pdf_bytes = render_pdf_bytes(req.doc) except Exception as exc: raise HTTPException( status_code=500, detail=f"Error al generar PDF: {exc}", ) filename = f"{job_id}.pdf" return StreamingResponse( io.BytesIO(pdf_bytes), media_type="application/pdf", headers={"Content-Disposition": f'attachment; filename="{filename}"'}, )