import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { getPresignedUrl, BUCKET_NAME } from '@/lib/minio'

export async function POST(request: NextRequest): Promise<NextResponse> {
  const session = await auth()

  if (!session?.user?.id) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
  }

  try {
    const body = await request.json()
    const { projectId, fileIds } = body as {
      projectId?: string
      fileIds?: string[]
    }

    if (!projectId || !fileIds || !Array.isArray(fileIds) || fileIds.length === 0) {
      return NextResponse.json(
        { error: 'projectId and fileIds array are required' },
        { status: 400 }
      )
    }

    const userId = session.user.id
    const userRole = session.user.role

    // Authorization: must be admin or assigned jury/mentor for this project
    const isAdmin = userRole === 'SUPER_ADMIN' || userRole === 'PROGRAM_ADMIN'

    // Per-round scope: jurors may only pull URLs for files in rounds with
    // sortOrder <= their assigned round. Mirrors file.getDownloadUrl. Without
    // this, a juror assigned to EVALUATION could bulk-download LIVE_FINAL
    // confidential files via this endpoint.
    let priorRoundIds: string[] | null = null

    if (!isAdmin) {
      const juryAssignment = await prisma.assignment.findFirst({
        where: { userId, projectId },
        select: { id: true, roundId: true },
      })

      const mentorAssignment = await prisma.mentorAssignment.findFirst({
        where: { mentorId: userId, projectId },
        select: { id: true },
      })

      if (!juryAssignment && !mentorAssignment) {
        return NextResponse.json(
          { error: 'You do not have access to this project\'s files' },
          { status: 403 }
        )
      }

      // Apply the per-round filter only when access is jury-only.
      if (juryAssignment && !mentorAssignment) {
        const assignedRound = await prisma.round.findUnique({
          where: { id: juryAssignment.roundId },
          select: { competitionId: true, sortOrder: true },
        })
        if (assignedRound) {
          const priorOrCurrent = await prisma.round.findMany({
            where: {
              competitionId: assignedRound.competitionId,
              sortOrder: { lte: assignedRound.sortOrder },
            },
            select: { id: true },
          })
          priorRoundIds = priorOrCurrent.map((r) => r.id)
        }
      }
    }

    // Fetch file metadata from DB
    const fileWhere: Record<string, unknown> = {
      id: { in: fileIds },
      projectId,
    }
    if (priorRoundIds !== null) {
      fileWhere.OR = [
        { requirement: { roundId: { in: priorRoundIds } } },
        { requirementId: null, roundId: { in: priorRoundIds } },
        { requirementId: null, roundId: null },
      ]
    }

    const files = await prisma.projectFile.findMany({
      where: fileWhere,
      select: {
        id: true,
        fileName: true,
        objectKey: true,
        mimeType: true,
        size: true,
      },
    })

    if (files.length === 0) {
      return NextResponse.json(
        { error: 'No matching files found' },
        { status: 404 }
      )
    }

    // Generate signed download URLs for each file
    const downloadUrls = await Promise.all(
      files.map(async (file) => {
        try {
          const downloadUrl = await getPresignedUrl(
            BUCKET_NAME,
            file.objectKey,
            'GET',
            3600 // 1 hour expiry for bulk downloads
          )

          return {
            id: file.id,
            fileName: file.fileName,
            mimeType: file.mimeType,
            size: file.size,
            downloadUrl,
          }
        } catch (error) {
          console.error(`[BulkDownload] Failed to get URL for file ${file.id}:`, error)
          return {
            id: file.id,
            fileName: file.fileName,
            mimeType: file.mimeType,
            size: file.size,
            downloadUrl: null,
            error: 'Failed to generate download URL',
          }
        }
      })
    )

    return NextResponse.json({
      projectId,
      files: downloadUrls,
      expiresIn: 3600,
    })
  } catch (error) {
    console.error('[BulkDownload] Error:', error)
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    )
  }
}
