import { z } from 'zod';
import { planFeatureFlagsSchema } from './plan';

const dayOfWeekEnum = z.enum([
  'MONDAY',
  'TUESDAY',
  'WEDNESDAY',
  'THURSDAY',
  'FRIDAY',
  'SATURDAY',
  'SUNDAY',
]);

export const complexSchema = z.object({
  id: z.uuid(),
  complexName: z.string(),
  physicalAddress: z.string().nullable(),
  city: z.string().nullable(),
  state: z.string().nullable(),
  country: z.string().nullable(),
  complexSlug: z.string(),
  adminEmail: z.email(),
  planCode: z.string().max(10).nullable(),
  createdAt: z.string().datetime(),
  updatedAt: z.string().datetime(),
});

export const createComplexSchema = z
  .object({
    complexName: z
      .string()
      .trim()
      .min(3, 'El nombre del complejo debe tener al menos 3 caracteres.')
      .max(120, 'El nombre del complejo no puede superar los 120 caracteres.'),
    physicalAddress: z
      .string()
      .trim()
      .min(5, 'La direccion debe tener al menos 5 caracteres.')
      .max(200, 'La direccion no puede superar los 200 caracteres.'),
    city: z.string().trim().max(100, 'La ciudad no puede superar los 100 caracteres.').optional(),
    state: z
      .string()
      .trim()
      .max(100, 'La provincia/estado no puede superar los 100 caracteres.')
      .optional(),
    country: z.string().trim().max(100, 'El país no puede superar los 100 caracteres.').optional(),
    planCode: z
      .string()
      .trim()
      .min(1, 'El planCode no puede estar vacío.')
      .max(10, 'El planCode no puede superar los 10 caracteres.')
      .optional(),
    setupCourts: z.boolean().default(false),
    courtSportId: z.string().uuid('El deporte seleccionado no es válido.').optional(),
    courtStartTime: z.string().optional(),
    courtEndTime: z.string().optional(),
    courtDaysOfWeek: z.array(dayOfWeekEnum).optional(),
  })
  .superRefine((data, ctx) => {
    if (data.setupCourts) {
      if (!data.courtSportId) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          path: ['courtSportId'],
          message: 'Debes seleccionar un deporte.',
        });
      }
      if (!data.courtStartTime || !/^\d{2}:\d{2}$/.test(data.courtStartTime)) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          path: ['courtStartTime'],
          message: 'La hora de inicio debe tener formato HH:mm.',
        });
      }
      if (!data.courtEndTime || !/^\d{2}:\d{2}$/.test(data.courtEndTime)) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          path: ['courtEndTime'],
          message: 'La hora de fin debe tener formato HH:mm.',
        });
      }
      if (!data.courtDaysOfWeek || data.courtDaysOfWeek.length === 0) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          path: ['courtDaysOfWeek'],
          message: 'Debes seleccionar al menos un día.',
        });
      }
    }
  });

export const updateComplexSchema = z
  .object({
    complexName: z
      .string()
      .trim()
      .min(3, 'El nombre del complejo debe tener al menos 3 caracteres.')
      .max(120, 'El nombre del complejo no puede superar los 120 caracteres.')
      .optional(),
    physicalAddress: z
      .string()
      .trim()
      .min(5, 'La direccion debe tener al menos 5 caracteres.')
      .max(200, 'La direccion no puede superar los 200 caracteres.')
      .nullable()
      .optional(),
    city: z
      .string()
      .trim()
      .max(100, 'La ciudad no puede superar los 100 caracteres.')
      .nullable()
      .optional(),
    state: z
      .string()
      .trim()
      .max(100, 'La provincia/estado no puede superar los 100 caracteres.')
      .nullable()
      .optional(),
    country: z
      .string()
      .trim()
      .max(100, 'El país no puede superar los 100 caracteres.')
      .nullable()
      .optional(),
    complexSlug: z
      .string()
      .trim()
      .min(3, 'El slug del complejo debe tener al menos 3 caracteres.')
      .max(120, 'El slug del complejo no puede superar los 120 caracteres.')
      .optional(),
    adminEmail: z.email('El adminEmail debe ser un email válido.').optional(),
    planCode: z
      .string()
      .trim()
      .min(1, 'El planCode no puede estar vacío.')
      .max(10, 'El planCode no puede superar los 10 caracteres.')
      .nullable()
      .optional(),
  })
  .refine(
    (payload) =>
      Boolean(
        payload.complexName ||
          payload.physicalAddress !== undefined ||
          payload.city !== undefined ||
          payload.state !== undefined ||
          payload.country !== undefined ||
          payload.complexSlug ||
          payload.adminEmail ||
          payload.planCode !== undefined
      ),
    {
      message: 'Debes enviar al menos un campo para actualizar.',
    }
  );

export const complexUserRoleSchema = z.enum(['ADMIN', 'EMPLOYEE']);

export type ComplexUserRole = z.infer<typeof complexUserRoleSchema>;

export const complexMemberSchema = z.object({
  userId: z.string(),
  fullName: z.string(),
  email: z.email(),
  avatarUrl: z.url(),
  role: complexUserRoleSchema,
  createdAt: z.string().datetime(),
});

export type ComplexMember = z.infer<typeof complexMemberSchema>;

export const complexInvitationStatusSchema = z.enum(['PENDING', 'ACCEPTED', 'REVOKED', 'EXPIRED']);

export type ComplexInvitationStatus = z.infer<typeof complexInvitationStatusSchema>;

export const complexInvitationSchema = z.object({
  id: z.uuid(),
  complexId: z.uuid(),
  email: z.email(),
  status: complexInvitationStatusSchema,
  createdAt: z.string().datetime(),
  expiresAt: z.string().datetime(),
  acceptedAt: z.string().datetime().nullable(),
  revokedAt: z.string().datetime().nullable(),
});

export type ComplexInvitation = z.infer<typeof complexInvitationSchema>;

export const complexUsersOverviewSchema = z.object({
  members: z.array(complexMemberSchema),
  invitations: z.array(complexInvitationSchema),
});

export type ComplexUsersOverview = z.infer<typeof complexUsersOverviewSchema>;

export const inviteComplexUserSchema = z.object({
  email: z.email('El email debe ser válido.'),
});

export type InviteComplexUserInput = z.infer<typeof inviteComplexUserSchema>;

export const acceptComplexInvitationsSchema = z.object({
  inviteToken: z.string().min(1, 'El token de invitación no puede estar vacío.').optional(),
});

export type AcceptComplexInvitationsInput = z.infer<typeof acceptComplexInvitationsSchema>;

export const revokeComplexUserSchema = z.object({
  userId: z.string().min(1, 'El userId no puede estar vacío.'),
});

export type RevokeComplexUserInput = z.infer<typeof revokeComplexUserSchema>;

export const selectComplexSchema = z.object({
  complexId: z.string().uuid(),
});

export type SelectComplexInput = z.infer<typeof selectComplexSchema>;

export const complexWithRoleSchema = complexSchema.merge(
  z.object({
    role: complexUserRoleSchema,
    planFeatures: planFeatureFlagsSchema.nullable(),
  })
);

export type ComplexWithRole = z.infer<typeof complexWithRoleSchema>;

export type Complex = z.infer<typeof complexSchema>;
export type CreateComplexInput = z.infer<typeof createComplexSchema>;
export type UpdateComplexInput = z.infer<typeof updateComplexSchema>;
export type CreateComplexPayload = CreateComplexInput;
export type CreateComplexResponse = Complex;
export type UpdateComplexPayload = UpdateComplexInput;
export type UpdateComplexResponse = Complex;
export type InviteComplexUserResponse = {
  invitation: ComplexInvitation;
};
export type AcceptComplexInvitationsResponse = {
  acceptedCount: number;
};
export type CancelComplexInvitationResponse = {
  ok: boolean;
};
