import { NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import { safeHandler, requireAuth, AuthError } from '@/lib/auth'

export const GET = safeHandler(async (req: Request) => {
  await requireAuth()
  const { searchParams } = new URL(req.url)
  const status = searchParams.get('status') || ''
  const type = searchParams.get('type') || ''
  const bookingId = searchParams.get('bookingId') || ''

  const where: any = {}
  if (status) where.status = status
  if (type) where.type = type
  if (bookingId) where.bookingId = bookingId

  const invoices = await prisma.invoice.findMany({
    where: Object.keys(where).length > 0 ? where : undefined,
    include: {
      booking: {
        select: { bookingNo: true, query: { select: { leadName: true } } },
      },
    },
    orderBy: { createdAt: 'desc' },
  })

  return NextResponse.json(invoices)
})

export const POST = safeHandler(async (req: Request) => {
  const { userId } = await requireAuth()
  const data = await req.json()

  if (!data.bookingId) {
    throw new AuthError('Booking is required', 400)
  }

  // Determine prefix and docType based on invoice type
  const invoiceType = data.type || 'PROFORMA'
  const isProforma = invoiceType === 'PROFORMA'
  const prefix = isProforma ? 'PRF' : 'INV'
  const docType = isProforma ? 'PROFORMA' : 'INVOICE'

  // Find or create number series
  let series = await prisma.numberSeries.findFirst({
    where: { module: 'invoicing', docType },
  })
  if (!series) {
    series = await prisma.numberSeries.create({
      data: {
        prefix,
        module: 'invoicing',
        docType,
        nextNumber: 1,
        format: '{PREFIX}-{YEAR}-{NUM:4}',
      },
    })
  }

  const year = new Date().getFullYear().toString().slice(-2)
  const num = series.nextNumber.toString().padStart(4, '0')
  const invoiceNo = `${series.prefix}-${year}-${num}`

  // Prepare items
  const items = (data.items || []).map((item: any, index: number) => {
    const quantity = parseInt(item.quantity) || 1
    const unitPrice = parseFloat(item.unitPrice) || 0
    const totalPrice = quantity * unitPrice
    return {
      description: item.description,
      hsnCode: item.hsnCode || null,
      quantity,
      unitPrice,
      totalPrice,
      sortOrder: item.sortOrder ?? index,
    }
  })

  // Calculate totals
  const subtotal = items.reduce((sum: number, item: any) => sum + item.totalPrice, 0)
  const cgstRate = parseFloat(data.cgstRate) || 0
  const sgstRate = parseFloat(data.sgstRate) || 0
  const igstRate = parseFloat(data.igstRate) || 0
  const cgstAmount = subtotal * cgstRate / 100
  const sgstAmount = subtotal * sgstRate / 100
  const igstAmount = subtotal * igstRate / 100
  const totalTax = cgstAmount + sgstAmount + igstAmount
  const totalAmount = subtotal + totalTax

  const invoice = await prisma.$transaction(async (tx) => {
    const newInvoice = await tx.invoice.create({
      data: {
        invoiceNo,
        bookingId: data.bookingId,
        type: invoiceType,
        status: data.status || 'DRAFT',
        issueDate: data.issueDate ? new Date(data.issueDate) : new Date(),
        dueDate: data.dueDate ? new Date(data.dueDate) : null,
        clientName: data.clientName,
        clientEmail: data.clientEmail || null,
        clientPhone: data.clientPhone || null,
        clientGstNumber: data.clientGstNumber || null,
        clientPanNumber: data.clientPanNumber || null,
        clientAddress: data.clientAddress || null,
        subtotal,
        cgstRate,
        cgstAmount,
        sgstRate,
        sgstAmount,
        igstRate,
        igstAmount,
        totalTax,
        totalAmount,
        currency: data.currency || 'INR',
        notes: data.notes || null,
        termsConditions: data.termsConditions || null,
        createdById: userId,
        items: {
          create: items,
        },
      },
      include: {
        items: { orderBy: { sortOrder: 'asc' } },
        booking: {
          select: { bookingNo: true, query: { select: { leadName: true } } },
        },
      },
    })

    // Increment the number series
    await tx.numberSeries.update({
      where: { id: series!.id },
      data: { nextNumber: { increment: 1 } },
    })

    return newInvoice
  })

  return NextResponse.json(invoice, { status: 201 })
})
