"""MediaAsset router — /api/media.""" import io import uuid import zipfile from fastapi import APIRouter, Depends, HTTPException, Query from fastapi.responses import StreamingResponse from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.domains.media.models import MediaAssetType from app.domains.media.schemas import MediaAssetOut from app.domains.media import service router = APIRouter(prefix="/api/media", tags=["media"]) @router.get("/", response_model=list[MediaAssetOut]) async def list_assets( product_id: uuid.UUID | None = None, order_line_id: uuid.UUID | None = None, asset_type: MediaAssetType | None = None, skip: int = Query(0, ge=0), limit: int = Query(50, ge=1, le=500), db: AsyncSession = Depends(get_db), ): assets = await service.list_media_assets( db, product_id=product_id, order_line_id=order_line_id, asset_type=asset_type, skip=skip, limit=limit, ) for a in assets: a.download_url = service.get_download_url(a) return assets @router.get("/{asset_id}", response_model=MediaAssetOut) async def get_asset(asset_id: uuid.UUID, db: AsyncSession = Depends(get_db)): asset = await service.get_media_asset(db, asset_id) if not asset: raise HTTPException(404, "Asset not found") asset.download_url = service.get_download_url(asset) return asset @router.get("/{asset_id}/download") async def download_asset(asset_id: uuid.UUID, db: AsyncSession = Depends(get_db)): from fastapi.responses import RedirectResponse asset = await service.get_media_asset(db, asset_id) if not asset: raise HTTPException(404, "Asset not found") url = service.get_download_url(asset) if url: return RedirectResponse(url) raise HTTPException(404, "File not available") @router.post("/zip") async def zip_download( asset_ids: list[uuid.UUID], db: AsyncSession = Depends(get_db), ): assets = [] for aid in asset_ids: a = await service.get_media_asset(db, aid) if a: assets.append(a) if not assets: raise HTTPException(404, "No assets found") def generate(): buf = io.BytesIO() with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf: from app.core.storage import get_storage storage = get_storage() for a in assets: ext = (a.mime_type or "").split("/")[-1] or "bin" fname = f"{a.asset_type.value}_{a.id}.{ext}" try: data = storage.download_bytes(a.storage_key) zf.writestr(fname, data) except Exception: pass yield buf.getvalue() return StreamingResponse( generate(), media_type="application/zip", headers={"Content-Disposition": "attachment; filename=media-export.zip"}, ) @router.delete("/{asset_id}") async def archive_asset(asset_id: uuid.UUID, db: AsyncSession = Depends(get_db)): asset = await service.archive_media_asset(db, asset_id) if not asset: raise HTTPException(404, "Asset not found") return {"ok": True}