import type { UpdateBookingDetailsResponse } from '~~/shared/booking' import { getHeader, readMultipartFormData } from 'h3' import { getBookingByConfirmationToken, replaceBookingTransactionDocumentByConfirmationToken } 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 token = getRequiredRouteParam(event, 'token', 'Confirmation token') const booking = await getBookingByConfirmationToken(token, { includeTransactionDocument: true }) if (!booking) { httpError(404, 'Booking not found') } if (booking.status !== 'pending') { httpError(409, 'Transaction document can only be changed before confirmation') } 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 replaceBookingTransactionDocumentByConfirmationToken({ confirmationToken: token, 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 } })