import { z } from 'zod';

const TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d)$/;
const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
const BOOKING_CODE_REGEX = /^[A-Z0-9]{6,8}$/;

export const bookingStatusSchema = z.enum(['CONFIRMED', 'CANCELLED', 'COMPLETED', 'NOSHOW']);

export const recurringGroupStatusSchema = z.enum(['ACTIVE', 'CANCELLED']);

export const adminBookingSportSchema = z.object({
  id: z.uuid(),
  name: z.string(),
  slug: z.string(),
});

export const adminBookingSchema = z.object({
  id: z.uuid(),
  bookingCode: z.string().regex(BOOKING_CODE_REGEX),
  complexId: z.uuid(),
  complexName: z.string(),
  courtId: z.uuid(),
  courtName: z.string(),
  sport: adminBookingSportSchema,
  date: z.string().regex(ISO_DATE_REGEX),
  startTime: z.string().regex(TIME_REGEX),
  endTime: z.string().regex(TIME_REGEX),
  customerName: z.string(),
  customerPhone: z.string(),
  customerEmail: z.string(),
  price: z.number().nonnegative(),
  status: bookingStatusSchema,
  recurringGroupId: z.string().uuid().nullable().optional(),
  createdAt: z.string().datetime(),
  updatedAt: z.string().datetime(),
});

export const listAdminBookingsQuerySchema = z.object({
  fromDate: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'),
});

export const listAdminBookingsResponseSchema = z.object({
  bookings: z.array(adminBookingSchema),
});

export const createAdminBookingSchema = z.object({
  date: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'),
  courtId: z.uuid('El courtId debe ser un UUID valido.'),
  startTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.'),
  customerName: z
    .string()
    .trim()
    .min(2, 'El nombre debe tener al menos 2 caracteres.')
    .max(120, 'El nombre no puede superar los 120 caracteres.'),
  customerPhone: z
    .string()
    .trim()
    .min(6, 'El telefono debe tener al menos 6 caracteres.')
    .max(30, 'El telefono no puede superar los 30 caracteres.'),
  customerEmail: z.string().email('El email ingresado no es valido.').or(z.literal('')),
});

export const updateAdminBookingStatusSchema = z.object({
  status: z.enum(['CANCELLED', 'COMPLETED', 'NOSHOW']),
});

export const createRecurringBookingSchema = createAdminBookingSchema.extend({
  isRecurring: z.literal(true),
  recurringEndDate: z
    .string()
    .regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.')
    .optional(),
});

export const recurringBookingGroupSchema = z.object({
  id: z.uuid(),
  complexId: z.uuid(),
  courtId: z.uuid(),
  startTime: z.string().regex(TIME_REGEX),
  endTime: z.string().regex(TIME_REGEX),
  dayOfWeek: z.enum(['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY']),
  startDate: z.string().regex(ISO_DATE_REGEX),
  endDate: z.string().regex(ISO_DATE_REGEX).nullable(),
  status: recurringGroupStatusSchema,
  customerName: z.string(),
  customerPhone: z.string(),
  customerEmail: z.string(),
  bookings: z.array(adminBookingSchema),
  createdAt: z.string().datetime(),
  updatedAt: z.string().datetime(),
});

export const updateRecurringGroupSchema = z.object({
  courtId: z.uuid('El courtId debe ser un UUID valido.').optional(),
  dayOfWeek: z
    .enum(['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY'])
    .optional(),
  startTime: z.string().regex(TIME_REGEX, 'La hora debe tener formato HH:mm.').optional(),
  customerName: z
    .string()
    .trim()
    .min(2, 'El nombre debe tener al menos 2 caracteres.')
    .max(120, 'El nombre no puede superar los 120 caracteres.')
    .optional(),
  customerPhone: z
    .string()
    .trim()
    .min(6, 'El telefono debe tener al menos 6 caracteres.')
    .max(30, 'El telefono no puede superar los 30 caracteres.')
    .optional(),
  customerEmail: z.string().email('El email ingresado no es valido.').or(z.literal('')).optional(),
});

export const listRecurringGroupsResponseSchema = z.object({
  groups: z.array(recurringBookingGroupSchema),
});

export type BookingStatus = z.infer<typeof bookingStatusSchema>;
export type RecurringGroupStatus = z.infer<typeof recurringGroupStatusSchema>;
export type AdminBookingSport = z.infer<typeof adminBookingSportSchema>;
export type AdminBooking = z.infer<typeof adminBookingSchema>;
export type ListAdminBookingsQuery = z.infer<typeof listAdminBookingsQuerySchema>;
export type ListAdminBookingsResponse = z.infer<typeof listAdminBookingsResponseSchema>;
export type CreateAdminBookingInput = z.infer<typeof createAdminBookingSchema>;
export type CreateRecurringBookingInput = z.infer<typeof createRecurringBookingSchema>;
export type RecurringBookingGroup = z.infer<typeof recurringBookingGroupSchema>;
export type UpdateAdminBookingStatusInput = z.infer<typeof updateAdminBookingStatusSchema>;
export type UpdateRecurringGroupInput = z.infer<typeof updateRecurringGroupSchema>;
export type ListRecurringGroupsResponse = z.infer<typeof listRecurringGroupsResponseSchema>;
