import { NextRequest, NextResponse } from 'next/server'; import { getSession } from '@/lib/session'; import { db } from '@/lib/db'; import { bookings, settings } from '@/lib/db/schema'; import { eq, and } from 'drizzle-orm'; import { logActivity, ACTIONS, ENTITY_TYPES } from '@/lib/activity-logger'; export async function PATCH(request: NextRequest, context: { params: Promise<{ id: string }> }) { try { const session = await getSession(); if (!session) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { notes } = await request.json(); const { id } = await context.params; const bookingId = id; // Check if booking exists and belongs to user const existingBooking = await db .select() .from(bookings) .where(and(eq(bookings.id, bookingId), eq(bookings.userId, session.userId), eq(bookings.status, 'active'))) .limit(1); if (existingBooking.length === 0) { return NextResponse.json({ error: 'Booking not found or access denied' }, { status: 404 }); } const booking = existingBooking[0]; // Check if booking modifications are allowed const modificationSetting = await db .select() .from(settings) .where(eq(settings.key, 'allow_booking_modifications')) .limit(1); if (modificationSetting.length > 0 && modificationSetting[0].value !== 'true') { return NextResponse.json( { error: 'Booking modifications are currently disabled by administrator' }, { status: 400 } ); } // Get the time restriction setting const timeSetting = await db .select() .from(settings) .where(eq(settings.key, 'booking_modification_hours_before')) .limit(1); const requiredHours = timeSetting.length > 0 ? parseFloat(timeSetting[0].value) : 2; // Check if booking can be modified (more than required hours before start time) const bookingDateTime = new Date(`${booking.date}T${booking.startTime}`); const now = new Date(); const timeDiff = bookingDateTime.getTime() - now.getTime(); const hoursDiff = timeDiff / (1000 * 60 * 60); if (hoursDiff <= requiredHours) { return NextResponse.json( { error: `Booking can only be modified more than ${requiredHours} hours before the session` }, { status: 400 } ); } // Update booking notes await db .update(bookings) .set({ notes: notes || null, updatedAt: new Date(), }) .where(eq(bookings.id, bookingId)); // Log the activity await logActivity({ userId: session.userId, action: ACTIONS.BOOKING_UPDATE, entityType: ENTITY_TYPES.BOOKING, entityId: bookingId, details: { oldNotes: booking.notes, newNotes: notes, date: booking.date, startTime: booking.startTime, }, request, }); return NextResponse.json({ success: true, message: 'Booking updated successfully', }); } catch (error) { console.error('Error updating booking:', error); return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); } } export async function DELETE(request: NextRequest, context: { params: Promise<{ id: string }> }) { try { const session = await getSession(); if (!session) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { id } = await context.params; const bookingId = id; // Check if booking exists and belongs to user const existingBooking = await db .select() .from(bookings) .where(and(eq(bookings.id, bookingId), eq(bookings.userId, session.userId), eq(bookings.status, 'active'))) .limit(1); if (existingBooking.length === 0) { return NextResponse.json({ error: 'Booking not found or access denied' }, { status: 404 }); } const booking = existingBooking[0]; // Check if booking modifications are allowed const modificationSetting = await db .select() .from(settings) .where(eq(settings.key, 'allow_booking_modifications')) .limit(1); if (modificationSetting.length > 0 && modificationSetting[0].value !== 'true') { return NextResponse.json( { error: 'Booking modifications are currently disabled by administrator' }, { status: 400 } ); } // Get the time restriction setting const timeSetting = await db .select() .from(settings) .where(eq(settings.key, 'booking_modification_hours_before')) .limit(1); const requiredHours = timeSetting.length > 0 ? parseFloat(timeSetting[0].value) : 2; // Check if booking can be cancelled (more than required hours before start time) const bookingDateTime = new Date(`${booking.date}T${booking.startTime}`); const now = new Date(); const timeDiff = bookingDateTime.getTime() - now.getTime(); const hoursDiff = timeDiff / (1000 * 60 * 60); if (hoursDiff <= requiredHours) { return NextResponse.json( { error: `Booking can only be cancelled more than ${requiredHours} hours before the session` }, { status: 400 } ); } // Cancel booking (set status to cancelled) await db .update(bookings) .set({ status: 'cancelled', updatedAt: new Date(), }) .where(eq(bookings.id, bookingId)); // Log the activity await logActivity({ userId: session.userId, action: ACTIONS.BOOKING_CANCEL, entityType: ENTITY_TYPES.BOOKING, entityId: bookingId, details: { date: booking.date, startTime: booking.startTime, endTime: booking.endTime, courtId: booking.courtId, }, request, }); return NextResponse.json({ success: true, message: 'Booking cancelled successfully', }); } catch (error) { console.error('Error cancelling booking:', error); return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); } }