import type { UpdateBookingDetailsResponse } from '~~/shared/booking' import { getHeader, readMultipartFormData } from 'h3' import { requireAuth } from '../../../utils/auth' import { getBookingById, replaceBookingTransactionDocument } from '../../../utils/booking-repository' import { getRequiredRouteParam, httpError } from '../../../utils/http' import { deleteTransactionDocument, saveTransactionDocument, TRANSACTION_DOCUMENT_MAX_SIZE, validateTransactionDocumentUpload } from '../../../utils/transaction-documents' export default defineEventHandler(async (event): Promise => { const auth = await requireAuth(event) const bookingId = getRequiredRouteParam(event, 'id', 'Booking ID') const accessScope = auth.user.role === 'super_admin' ? undefined : { personInChargeId: auth.user.id } const booking = await getBookingById(bookingId, accessScope) if (!booking) { httpError(404, 'Booking not found') } if (booking.paymentMethod !== 'bank') { httpError(400, 'Transaction document can only be uploaded for Bank payments') } const contentType = String(getHeader(event, 'content-type') || '').toLowerCase() if (!contentType.startsWith('multipart/form-data;')) { httpError(400, 'Transaction document upload must use multipart form data') } const contentLength = Number(getHeader(event, 'content-length') || 0) if (contentLength > TRANSACTION_DOCUMENT_MAX_SIZE + 1024 * 1024) { httpError(413, 'Transaction document must be 10MB or smaller') } const formData = await readMultipartFormData(event) const filePart = formData?.find((part) => part.name === 'document' && part.filename) if (!filePart) { httpError(400, 'Transaction document is required') } const upload = validateTransactionDocumentUpload({ data: filePart.data, filename: filePart.filename, contentType: filePart.type }) const storageName = await saveTransactionDocument(filePart.data, upload.fileType) try { const result = await replaceBookingTransactionDocument({ bookingId, personInChargeId: auth.user.role === 'super_admin' ? undefined : auth.user.id, originalName: upload.originalName, storageName, mimeType: upload.fileType.mimeType, size: filePart.data.length }) if (!result) { await deleteTransactionDocument(storageName) httpError(404, 'Booking not found') } await deleteTransactionDocument(result.previousStorageName) return { booking: result.booking } } catch (error) { await deleteTransactionDocument(storageName) throw error } })