import { Errors } from '@/lib/errors'; import { db } from '@/lib/prisma'; import type { Result } from '@/lib/result'; import { err, ok } from '@/lib/result'; import type { UpdateAdminBookingStatusInput } from '@repo/api-contract'; import { v7 as uuidv7 } from 'uuid'; import { mapBookingResponse } from '../../shared/helpers'; export async function updateAdminBookingStatus( userId: string, bookingId: string, input: UpdateAdminBookingStatusInput ): Promise>> { const booking = await db.courtBooking.findFirst({ where: { id: bookingId, court: { complex: { users: { some: { userId } } }, }, }, include: { court: { select: { id: true, name: true, sport: { select: { id: true, name: true, slug: true } }, complex: { select: { id: true, complexName: true } }, }, }, }, }); if (!booking) { return err(Errors.notFound('Reserva no encontrada.')); } if (input.status === 'CANCELLED' && booking.status !== 'CONFIRMED') { return err(Errors.conflict('Solo se pueden cancelar reservas en estado confirmada.')); } if (input.status === 'COMPLETED' && booking.status !== 'CONFIRMED') { return err(Errors.conflict('Solo se pueden marcar como cumplidas las reservas confirmadas.')); } if (input.status === 'NOSHOW' && booking.status !== 'CONFIRMED') { return err(Errors.conflict('Solo se pueden marcar como no show las reservas confirmadas.')); } await db.courtBookingLog.create({ data: { id: uuidv7(), bookingCode: booking.bookingCode, courtId: booking.court.id, bookingDate: booking.bookingDate, startTime: booking.startTime, endTime: booking.endTime, customerName: booking.customerName, customerPhone: booking.customerPhone, customerEmail: booking.customerEmail, previousStatus: booking.status, newStatus: input.status, changedAt: new Date(), }, }); if (input.status === 'COMPLETED' || input.status === 'NOSHOW') { await db.courtBooking.update({ where: { id: booking.id }, data: { status: input.status }, }); } else { await db.courtBooking.delete({ where: { id: booking.id } }); } return ok(mapBookingResponse({ ...booking, status: input.status })); }