import { z } from 'zod';
import { dayOfWeekSchema } from './court';

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 publicAvailabilityQuerySchema = z.object({
  date: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'),
  sportId: z.uuid('El sportId debe ser un UUID valido.').optional(),
});

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

export const publicBookingSlotSchema = z.object({
  startTime: z.string().regex(TIME_REGEX),
  endTime: z.string().regex(TIME_REGEX),
  price: z.number().nonnegative(),
});

export const publicAvailabilityCourtSchema = z.object({
  courtId: z.uuid(),
  courtName: z.string(),
  sport: publicBookingSportSchema,
  slotDurationMinutes: z.int().positive(),
  availabilityDay: dayOfWeekSchema,
  availableSlots: z.array(publicBookingSlotSchema),
});

export const publicAvailabilityResponseSchema = z.object({
  complexId: z.uuid(),
  complexName: z.string(),
  complexAddress: z.string().optional(),
  complexSlug: z.string(),
  date: z.string().regex(ISO_DATE_REGEX),
  sportSelectionRequired: z.boolean(),
  sports: z.array(publicBookingSportSchema),
  courts: z.array(publicAvailabilityCourtSchema),
});

export const createPublicBookingSchema = z.object({
  date: z.string().regex(ISO_DATE_REGEX, 'La fecha debe tener formato YYYY-MM-DD.'),
  sportId: z.uuid('El sportId debe ser un UUID valido.').optional(),
  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.'),
});

export const cancelPublicBookingSchema = z.object({
  bookingCode: z.string().regex(BOOKING_CODE_REGEX, 'El codigo de reserva no es valido.'),
  customerPhone: z
    .string()
    .trim()
    .min(6, 'El telefono debe tener al menos 6 caracteres.')
    .max(30, 'El telefono no puede superar los 30 caracteres.'),
});

export const publicBookingSchema = z.object({
  id: z.uuid(),
  bookingCode: z.string().regex(BOOKING_CODE_REGEX),
  complexId: z.uuid(),
  complexName: z.string(),
  complexSlug: z.string(),
  courtId: z.uuid(),
  courtName: z.string(),
  sport: publicBookingSportSchema,
  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(),
  status: z.enum(['CONFIRMED', 'CANCELLED', 'COMPLETED']),
  price: z.number().nonnegative(),
  createdAt: z.string().datetime(),
});

export const publicBookingConfirmationSchema = z.object({
  bookingCode: z.string().regex(BOOKING_CODE_REGEX),
  complexName: z.string(),
  complexAddress: z.string().optional(),
  complexSlug: z.string(),
  date: z.string().regex(ISO_DATE_REGEX),
  startTime: z.string().regex(TIME_REGEX),
  endTime: z.string().regex(TIME_REGEX),
  price: z.number().nonnegative(),
  courtName: z.string(),
  sport: publicBookingSportSchema,
  status: z.enum(['CONFIRMED', 'CANCELLED', 'COMPLETED']),
  customerEmail: z.string(),
  createdAt: z.string().datetime(),
});

export type PublicAvailabilityQuery = z.infer<typeof publicAvailabilityQuerySchema>;
export type PublicBookingSport = z.infer<typeof publicBookingSportSchema>;
export type PublicBookingSlot = z.infer<typeof publicBookingSlotSchema>;
export type PublicAvailabilityCourt = z.infer<typeof publicAvailabilityCourtSchema>;
export type PublicAvailabilityResponse = z.infer<typeof publicAvailabilityResponseSchema>;
export type CreatePublicBookingInput = z.infer<typeof createPublicBookingSchema>;
export type CancelPublicBookingInput = z.infer<typeof cancelPublicBookingSchema>;
export type PublicBooking = z.infer<typeof publicBookingSchema>;
export type PublicBookingConfirmation = z.infer<typeof publicBookingConfirmationSchema>;
