import { NextRequest, NextResponse } from 'next/server' import { requireAuth } from '@/lib/auth' import { getUploadSession, markChunkUploaded, generatePresignedUrl } from '@/lib/upload' import { writeFile, mkdir } from 'fs/promises' import { join } from 'path' export async function POST( request: NextRequest, { params }: { params: Promise<{ uploadId: string; chunkIndex: string }> } ) { try { const user = await requireAuth() const { uploadId, chunkIndex: chunkIndexStr } = await params const chunkIndex = parseInt(chunkIndexStr) if (isNaN(chunkIndex)) { return NextResponse.json( { error: 'Invalid chunk index' }, { status: 400 } ) } // Get upload session const uploadSession = await getUploadSession(uploadId, user.id) if (!uploadSession) { return NextResponse.json( { error: 'Upload session not found or expired' }, { status: 404 } ) } if (uploadSession.status === 'completed') { return NextResponse.json( { error: 'Upload already completed' }, { status: 400 } ) } if (chunkIndex < 0 || chunkIndex >= uploadSession.totalChunks) { return NextResponse.json( { error: 'Invalid chunk index' }, { status: 400 } ) } // Get the chunk data from the request const chunkData = await request.arrayBuffer() const expectedSize = Math.min(uploadSession.chunkSize, uploadSession.fileSize - chunkIndex * uploadSession.chunkSize) if (chunkData.byteLength !== expectedSize) { return NextResponse.json( { error: `Invalid chunk size. Expected ${expectedSize}, got ${chunkData.byteLength}` }, { status: 400 } ) } // In a real implementation, you would: // 1. Upload to S3/CloudStorage using the presigned URL // 2. Or store temporarily on disk/cloud storage // For now, we'll simulate by storing in a temporary directory const tempDir = join(process.cwd(), 'temp', 'uploads', uploadId) await mkdir(tempDir, { recursive: true }) const chunkPath = join(tempDir, `chunk-${chunkIndex}`) await writeFile(chunkPath, Buffer.from(chunkData)) // Mark chunk as uploaded const updatedSession = await markChunkUploaded(uploadId, chunkIndex) // Generate presigned URL for next chunk if not complete let nextPresignedUrl = null if (updatedSession.status !== 'completed' && chunkIndex + 1 < uploadSession.totalChunks) { const { url } = await generatePresignedUrl( `chunk-${chunkIndex + 1}-${uploadSession.fileName}`, uploadSession.mimeType ) nextPresignedUrl = url } return NextResponse.json( { success: true, chunkIndex, uploadedChunks: updatedSession.uploadedChunks, totalChunks: updatedSession.totalChunks, status: updatedSession.status, nextPresignedUrl, }, { status: 200 } ) } catch (error) { console.error('Chunk upload error:', error) if (error instanceof Error && error.message === 'Unauthorized') { return NextResponse.json( { error: 'Unauthorized' }, { status: 401 } ) } return NextResponse.json( { error: 'Failed to upload chunk' }, { status: 500 } ) } }