import uuid from typing import Optional from fastapi import APIRouter, Depends, File, Form, Query, UploadFile, status from fastapi.responses import FileResponse from sqlalchemy.ext.asyncio import AsyncSession from app.core.deps import get_current_user, get_db_session from app.schemas.acknowledgement import AcknowledgementCreate, AcknowledgementRead from app.schemas.common import PaginatedResponse from app.schemas.distribution import DistributionCreate, DistributionRead from app.schemas.document import DocumentCreate, DocumentDetail, DocumentSummary from app.schemas.document_version import DocumentVersionRead from app.services import document_service from app.utils.pagination import paginate router = APIRouter() @router.post( "/documents", response_model=DocumentSummary, status_code=status.HTTP_201_CREATED, ) async def create_document( payload: DocumentCreate, db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ) -> DocumentSummary: doc = await document_service.create_document(db, payload, current_user) return DocumentSummary.model_validate(doc) @router.get("/documents", response_model=PaginatedResponse[DocumentSummary]) async def list_documents( trial_id: uuid.UUID = Query(...), site_id: Optional[uuid.UUID] = Query(None), doc_type: Optional[str] = Query(None), scope_type: Optional[str] = Query(None), status_value: Optional[str] = Query(None, alias="status"), skip: int = 0, limit: int = 100, db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ) -> PaginatedResponse[DocumentSummary]: items = await document_service.list_documents( db, trial_id=trial_id, site_id=site_id, doc_type=doc_type, status=status_value, scope_type=scope_type, skip=skip, limit=limit, current_user=current_user, ) return paginate(items, total=len(items)) @router.get("/documents/{document_id}", response_model=DocumentDetail) async def get_document_detail( document_id: uuid.UUID, db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ) -> DocumentDetail: return await document_service.get_document_detail(db, document_id, current_user) @router.delete("/documents/{document_id}", response_model=DocumentSummary) async def delete_document( document_id: uuid.UUID, db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ) -> DocumentSummary: doc = await document_service.delete_document(db, document_id, current_user) return DocumentSummary.model_validate(doc) @router.post( "/documents/{document_id}/versions", response_model=DocumentVersionRead, status_code=status.HTTP_201_CREATED, ) async def create_version( document_id: uuid.UUID, version_no: str = Form(...), version_date: str = Form(...), change_summary: Optional[str] = Form(None), parent_version_id: Optional[uuid.UUID] = Form(None), file: UploadFile = File(...), db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ) -> DocumentVersionRead: version = await document_service.create_version( db, document_id, version_no=version_no, version_date=version_date, change_summary=change_summary, parent_version_id=parent_version_id, file=file, current_user=current_user, ) return DocumentVersionRead.model_validate(version) @router.get("/versions/{version_id}/download", response_class=FileResponse) async def download_version( version_id: uuid.UUID, db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ): return await document_service.get_version_download_response(db, version_id, current_user) @router.delete("/versions/{version_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_version( version_id: uuid.UUID, db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ) -> None: await document_service.delete_version(db, version_id, current_user) @router.post( "/versions/{version_id}/distributions", response_model=list[DistributionRead], status_code=status.HTTP_201_CREATED, ) async def create_distributions( version_id: uuid.UUID, payload: DistributionCreate, db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ) -> list[DistributionRead]: distributions = await document_service.create_distributions(db, version_id, payload, current_user) return [DistributionRead.model_validate(d) for d in distributions] @router.get("/versions/{version_id}/distributions", response_model=list[DistributionRead]) async def list_distributions( version_id: uuid.UUID, db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ) -> list[DistributionRead]: return await document_service.list_distributions(db, version_id, current_user) @router.post( "/distributions/{distribution_id}/acknowledgements", response_model=AcknowledgementRead, status_code=status.HTTP_201_CREATED, ) async def create_acknowledgement( distribution_id: uuid.UUID, payload: AcknowledgementCreate, db: AsyncSession = Depends(get_db_session), current_user=Depends(get_current_user), ) -> AcknowledgementRead: ack = await document_service.create_acknowledgement(db, distribution_id, payload, current_user) return AcknowledgementRead.model_validate(ack)