import { NextResponse } from 'next/server'
import { format } from 'date-fns'
import { prisma } from '@/lib/prisma'
import { safeHandler, requireAuth } from '@/lib/auth'

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

  if (view === 'monthly') {
    // Monthly aggregation
    const monthStr = searchParams.get('month') || format(new Date(), 'yyyy-MM')
    const [year, month] = monthStr.split('-').map(Number)
    const start = new Date(year, month - 1, 1)
    const end = new Date(year, month, 0, 23, 59, 59)
    start.setDate(start.getDate() - 7)
    end.setDate(end.getDate() + 7)

    const operations = await prisma.dailyOperation.findMany({
      where: { date: { gte: start, lte: end }, operationType: { in: ['PICKUP', 'DROP', 'TRANSFER', 'SIGHTSEEING', 'ACTIVITY'] } },
      select: { date: true, driverId: true, driverName: true, startTime: true, endTime: true, id: true },
    })

    // Group by date, calculate daily aggregates
    const dailyMap: Record<string, { date: string; totalOps: number; driverIds: Set<string>; conflicts: number }> = {}
    for (const op of operations) {
      const dateKey = format(op.date, 'yyyy-MM-dd')
      if (!dailyMap[dateKey]) dailyMap[dateKey] = { date: dateKey, totalOps: 0, driverIds: new Set(), conflicts: 0 }
      dailyMap[dateKey].totalOps++
      if (op.driverId) dailyMap[dateKey].driverIds.add(op.driverId)
    }

    // Detect conflicts per day
    const byDateDriver: Record<string, typeof operations> = {}
    for (const op of operations) {
      const key = `${format(op.date, 'yyyy-MM-dd')}_${op.driverId || op.driverName || 'unassigned'}`
      if (!byDateDriver[key]) byDateDriver[key] = []
      byDateDriver[key].push(op)
    }
    for (const [key, ops] of Object.entries(byDateDriver)) {
      const dateKey = key.split('_')[0]
      if (!key.includes('unassigned')) {
        for (let i = 0; i < ops.length; i++) {
          for (let j = i + 1; j < ops.length; j++) {
            if (ops[i].startTime && ops[j].startTime &&
                ops[i].startTime < (ops[j].endTime || '23:59') &&
                (ops[i].endTime || '23:59') > ops[j].startTime) {
              if (dailyMap[dateKey]) dailyMap[dateKey].conflicts++
            }
          }
        }
      }
    }

    const result = Object.values(dailyMap).map(d => ({
      date: d.date, totalOps: d.totalOps, driverCount: d.driverIds.size, conflicts: d.conflicts,
    }))
    return NextResponse.json(result)
  }

  // Timeline view (default) - daily Gantt data grouped by driver
  const dateStr = searchParams.get('date') || new Date().toISOString().slice(0, 10)
  const startOfDay = new Date(dateStr + 'T00:00:00.000Z')
  const endOfDay = new Date(dateStr + 'T23:59:59.999Z')

  const operations = await prisma.dailyOperation.findMany({
    where: { date: { gte: startOfDay, lte: endOfDay } },
    include: { booking: { select: { bookingNo: true, query: { select: { leadName: true } } } } },
    orderBy: [{ startTime: 'asc' }],
  })

  // Get all active drivers for rows
  const drivers = await prisma.driver.findMany({
    where: { isActive: true },
    include: { vehicle: { select: { registrationNo: true, vehicleType: true, name: true } } },
    orderBy: { name: 'asc' },
  })

  // Group operations by driver
  const driverOpsMap: Record<string, typeof operations> = {}
  const unassignedOps: typeof operations = []
  for (const op of operations) {
    if (op.driverId) {
      if (!driverOpsMap[op.driverId]) driverOpsMap[op.driverId] = []
      driverOpsMap[op.driverId].push(op)
    } else {
      unassignedOps.push(op)
    }
  }

  // Detect conflicts (same driver, overlapping times)
  const conflictIds = new Set<string>()
  for (const [, ops] of Object.entries(driverOpsMap)) {
    for (let i = 0; i < ops.length; i++) {
      for (let j = i + 1; j < ops.length; j++) {
        if (ops[i].startTime && ops[j].startTime &&
            ops[i].startTime < (ops[j].endTime || '23:59') &&
            (ops[i].endTime || '23:59') > ops[j].startTime) {
          conflictIds.add(ops[i].id)
          conflictIds.add(ops[j].id)
        }
      }
    }
  }

  const mapOp = (op: typeof operations[0]) => ({
    id: op.id,
    operationType: op.operationType,
    title: op.title,
    startTime: op.startTime,
    endTime: op.endTime,
    fromLocation: op.fromLocation,
    toLocation: op.toLocation,
    guestName: op.guestName,
    bookingNo: op.booking?.bookingNo || null,
    paxCount: op.paxCount,
    status: op.status,
    hasConflict: conflictIds.has(op.id),
  })

  // Only include drivers that have operations today
  const driverRows = drivers
    .filter(d => driverOpsMap[d.id]?.length > 0)
    .map(d => ({
      id: d.id,
      name: d.name,
      phone: d.phone,
      vehicleName: d.vehicle?.name || '',
      vehicleNo: d.vehicle?.registrationNo || '',
      vehicleType: d.vehicle?.vehicleType || '',
      operations: (driverOpsMap[d.id] || []).map(mapOp),
    }))

  const totalConflicts = conflictIds.size
  const totalOps = operations.length
  const totalDrivers = driverRows.length
  const utilization = totalDrivers > 0 ? Math.round((totalOps / (totalDrivers * 10)) * 100) : 0

  return NextResponse.json({
    drivers: driverRows,
    unassigned: unassignedOps.map(mapOp),
    summary: { totalOps, totalDrivers, conflicts: totalConflicts, utilization: Math.min(utilization, 100) },
  })
})
