from fastapi import APIRouter, Depends, Query from app.core.config import settings from app.repositories.audit import create_audit_event from app.repositories.scheme_version_pricing import replace_scheme_version_pricing_snapshot from app.schemas.publish_preview import ( PublishPreviewResponse, RemapApplyRequest, RemapApplyResponse, RemapPreviewRequest, RemapPreviewResponse, RemapPreviewSeatItem, ) from app.security.auth import require_api_key from app.services.draft_guard import get_current_draft_context from app.services.publish_preview import get_or_build_publish_preview_bundle from app.services.remap_service import apply_remap, preview_remap router = APIRouter() @router.post(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/pricing/snapshot") async def create_draft_pricing_snapshot( scheme_id: str, role: str = Depends(require_api_key), ): scheme, version = await get_current_draft_context(scheme_id) result = await replace_scheme_version_pricing_snapshot( scheme_id=scheme.scheme_id, scheme_version_id=version.scheme_version_id, ) await create_audit_event( scheme_id=scheme.scheme_id, event_type="draft.pricing.snapshot.created", object_type="pricing_snapshot", object_ref=version.scheme_version_id, details=result, ) return { "scheme_id": scheme.scheme_id, "scheme_version_id": version.scheme_version_id, **result, } @router.get(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/publish-preview", response_model=PublishPreviewResponse) async def get_publish_preview( scheme_id: str, baseline_scheme_version_id: str | None = Query(default=None), refresh: bool = Query(default=False), role: str = Depends(require_api_key), ): scheme, version = await get_current_draft_context(scheme_id) bundle = await get_or_build_publish_preview_bundle( scheme_id=scheme.scheme_id, scheme_version_id=version.scheme_version_id, baseline_override_scheme_version_id=baseline_scheme_version_id, refresh=refresh, ) return PublishPreviewResponse( scheme_id=scheme.scheme_id, scheme_version_id=version.scheme_version_id, artifacts=bundle["artifacts"], validation=bundle["validation"], structure_diff=bundle["structure_diff"], pricing_coverage=bundle["pricing_coverage"], summary=bundle["summary"], ) @router.post(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/remap/preview", response_model=RemapPreviewResponse) async def preview_draft_remap( scheme_id: str, payload: RemapPreviewRequest, role: str = Depends(require_api_key), ): scheme, version = await get_current_draft_context(scheme_id) items = await preview_remap( scheme_version_id=version.scheme_version_id, seat_record_ids=payload.seat_record_ids, from_sector_id=payload.from_sector_id, to_sector_id=payload.to_sector_id, from_group_id=payload.from_group_id, to_group_id=payload.to_group_id, ) return RemapPreviewResponse( scheme_id=scheme.scheme_id, scheme_version_id=version.scheme_version_id, matched_count=len(items), items=[RemapPreviewSeatItem(**item) for item in items], ) @router.post(f"{settings.api_v1_prefix}/schemes/{{scheme_id}}/draft/remap/apply", response_model=RemapApplyResponse) async def apply_draft_remap( scheme_id: str, payload: RemapApplyRequest, role: str = Depends(require_api_key), ): scheme, version = await get_current_draft_context(scheme_id) items = await apply_remap( scheme_version_id=version.scheme_version_id, seat_record_ids=payload.seat_record_ids, from_sector_id=payload.from_sector_id, to_sector_id=payload.to_sector_id, from_group_id=payload.from_group_id, to_group_id=payload.to_group_id, ) await create_audit_event( scheme_id=scheme.scheme_id, event_type="draft.remap.applied", object_type="draft_structure", object_ref=version.scheme_version_id, details={ "matched_count": len(items), "from_sector_id": payload.from_sector_id, "to_sector_id": payload.to_sector_id, "from_group_id": payload.from_group_id, "to_group_id": payload.to_group_id, }, ) return RemapApplyResponse( scheme_id=scheme.scheme_id, scheme_version_id=version.scheme_version_id, updated_count=len(items), items=[RemapPreviewSeatItem(**item) for item in items], )