// app/api/verify/route.ts
import { prisma } from '@/lib/prisma'
import { NextResponse } from 'next/server'
import bcrypt from 'bcrypt'
import { TransferStatus } from '@prisma/client'
import { rateLimit, resetRateLimit, clientKey } from '@/lib/rate-limit'

// 10 password attempts per transfer, per client, per 15 minutes.
const ATTEMPT_LIMIT = 10
const ATTEMPT_WINDOW_MS = 15 * 60 * 1000

export async function POST(req: Request) {
  const { id, password } = await req.json()

  if (!id || !password) {
    return NextResponse.json({ success: false, message: 'Missing ID or password' }, { status: 400 })
  }

  // Keyed before the DB lookup so throttling costs an attacker a request
  // regardless of whether the transfer exists.
  const key = `verify:${id}:${clientKey(req.headers)}`
  const limit = rateLimit(key, ATTEMPT_LIMIT, ATTEMPT_WINDOW_MS)
  if (!limit.allowed) {
    return NextResponse.json(
      { success: false, message: 'Too many attempts. Please try again later.' },
      { status: 429, headers: { 'Retry-After': String(limit.retryAfter) } }
    )
  }

  const transfer = await prisma.transfer.findUnique({
    where: { downloadUrl: id },
    include: { files: true },
  })

  if (!transfer) {
    return NextResponse.json({ success: false, message: 'Transfer not found' }, { status: 404 })
  }

  if (transfer.status !== TransferStatus.ACTIVE || transfer.expiresAt <= new Date()) {
    return NextResponse.json(
      { success: false, message: 'This transfer is no longer available' },
      { status: 410 }
    )
  }

  if (!transfer.passwordHash) {
    return NextResponse.json(
      { success: false, message: 'This transfer is not downloadable' },
      { status: 409 }
    )
  }

  const isValid = await bcrypt.compare(password, transfer.passwordHash)
  if (!isValid) {
    return NextResponse.json({ success: false, message: 'Incorrect password' }, { status: 401 })
  }

  // Correct password: clear the counter so an earlier typo does not throttle.
  resetRateLimit(key)

  // Explicit allow-list rather than spreading the row: `files` carries absolute
  // server paths, and the row carries passwordHash and the owning userId.
  const totalSize = transfer.files.reduce((sum, file) => sum + file.size, BigInt(0))

  return NextResponse.json({
    success: true,
    transfer: {
      senderEmail: transfer.senderEmail,
      message: transfer.message,
      createdAt: transfer.createdAt.toISOString(),
      expiresAt: transfer.expiresAt.toISOString(),
      totalFiles: transfer.totalFiles,
      totalSize: Number(totalSize),
      filenames: transfer.filenames ? JSON.parse(transfer.filenames) : [],
      files: transfer.files.map((file) => ({
        id: file.id,
        name: file.name,
        size: Number(file.size),
      })),
    },
  })
}
