# ============================================== # Breakpilot Drive - Unit Content Generation Routes # ============================================== # API endpoints for H5P content, worksheets, and PDF generation. # Extracted from unit_api.py for file-size compliance. from fastapi import APIRouter, HTTPException, Query, Depends from typing import Optional, Dict, Any import logging from unit_models import UnitDefinitionResponse from unit_helpers import get_optional_current_user, get_unit_database logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/units", tags=["Breakpilot Units"]) @router.get("/content/{unit_id}/h5p") async def generate_h5p_content( unit_id: str, locale: str = Query("de-DE", description="Target locale"), user: Optional[Dict[str, Any]] = Depends(get_optional_current_user) ) -> Dict[str, Any]: """ Generate H5P content items for a unit. Returns H5P-compatible content structures for: - Drag and Drop (vocabulary matching) - Fill in the Blanks (concept texts) - Multiple Choice (misconception targeting) """ from content_generators import generate_h5p_for_unit, H5PGenerator, generate_h5p_manifest # Get unit definition db = await get_unit_database() unit_def = None if db: try: unit = await db.get_unit_definition(unit_id) if unit: unit_def = unit.get("definition", {}) except Exception as e: logger.error(f"Failed to get unit for H5P generation: {e}") if not unit_def: raise HTTPException(status_code=404, detail=f"Unit not found: {unit_id}") try: generator = H5PGenerator(locale=locale) contents = generator.generate_from_unit(unit_def) manifest = generate_h5p_manifest(contents, unit_id) return { "unit_id": unit_id, "locale": locale, "generated_count": len(contents), "manifest": manifest, "contents": [c.to_h5p_structure() for c in contents] } except Exception as e: logger.error(f"H5P generation failed: {e}") raise HTTPException(status_code=500, detail=f"H5P generation failed: {str(e)}") @router.get("/content/{unit_id}/worksheet") async def generate_worksheet_html( unit_id: str, locale: str = Query("de-DE", description="Target locale"), user: Optional[Dict[str, Any]] = Depends(get_optional_current_user) ) -> Dict[str, Any]: """ Generate worksheet HTML for a unit. Returns HTML that can be: - Displayed in browser - Converted to PDF using weasyprint - Printed directly """ from content_generators import PDFGenerator # Get unit definition db = await get_unit_database() unit_def = None if db: try: unit = await db.get_unit_definition(unit_id) if unit: unit_def = unit.get("definition", {}) except Exception as e: logger.error(f"Failed to get unit for worksheet generation: {e}") if not unit_def: raise HTTPException(status_code=404, detail=f"Unit not found: {unit_id}") try: generator = PDFGenerator(locale=locale) worksheet = generator.generate_from_unit(unit_def) return { "unit_id": unit_id, "locale": locale, "title": worksheet.title, "sections": len(worksheet.sections), "html": worksheet.to_html() } except Exception as e: logger.error(f"Worksheet generation failed: {e}") raise HTTPException(status_code=500, detail=f"Worksheet generation failed: {str(e)}") @router.get("/content/{unit_id}/worksheet.pdf") async def download_worksheet_pdf( unit_id: str, locale: str = Query("de-DE", description="Target locale"), user: Optional[Dict[str, Any]] = Depends(get_optional_current_user) ): """ Generate and download worksheet as PDF. Requires weasyprint to be installed on the server. """ from fastapi.responses import Response # Get unit definition db = await get_unit_database() unit_def = None if db: try: unit = await db.get_unit_definition(unit_id) if unit: unit_def = unit.get("definition", {}) except Exception as e: logger.error(f"Failed to get unit for PDF generation: {e}") if not unit_def: raise HTTPException(status_code=404, detail=f"Unit not found: {unit_id}") try: from content_generators import generate_worksheet_pdf pdf_bytes = generate_worksheet_pdf(unit_def, locale) return Response( content=pdf_bytes, media_type="application/pdf", headers={ "Content-Disposition": f'attachment; filename="{unit_id}_worksheet.pdf"' } ) except ImportError: raise HTTPException( status_code=501, detail="PDF generation not available. Install weasyprint: pip install weasyprint" ) except Exception as e: logger.error(f"PDF generation failed: {e}") raise HTTPException(status_code=500, detail=f"PDF generation failed: {str(e)}")