import { z } from 'zod';
import { dateTransformSchema, defaultTransformSchema } from '../shared/shared.dto';

const optionalFileSchema = z
  .any()
  .transform((value) => {
    if (
      !value ||
      typeof value !== 'object' ||
      !('file_name' in value) ||
      typeof value.file_name !== 'string' ||
      value.file_name.trim() === ''
    ) {
      return undefined;
    }

    const host = process.env.SERVER_HOST ?? '';
    const hasHost = host.length > 0 && value.file_name.startsWith(host);

    return {
      ...value,
      file_name: hasHost ? value.file_name : `${host}/${value.file_name}`,
    };
  })
  .optional();

const optionalString = z.preprocess((value) => {
  if (typeof value === 'string' && value.trim() === '') return undefined;
  return value;
}, z.string().trim().optional());

const optionalDate = z.preprocess((value) => {
  if (value === null || value === undefined || value === '') return undefined;
  return value;
}, z.coerce.date().optional());

const eventTypeSchema = z.enum([
  'meeting',
  'training',
  'workshop',
  'conference',
  'social',
  'other',
]);

const eventMemberSchema = z.object({
  id: z.string().uuid(),
  employee_id: z.string(),
  first_name: z.string(),
  last_name: defaultTransformSchema,
  nickname: defaultTransformSchema,
  image: z.any().optional(),
});

export const createEventSchema = z
  .object({
    title: z.string().trim().min(2, { message: 'Event title is required' }),
    image: optionalFileSchema,
    category: eventTypeSchema.optional(),
    date: z.coerce.date({ message: 'Event date is required' }),
    start_time: z.coerce.date({ message: 'Start time is required' }),
    end_time: z.coerce.date({ message: 'End time is required' }),
    location: optionalString,
    event_owner: optionalString,
    description: optionalString,
    member_ids: z.array(z.string().uuid()).optional(),
  })
  .superRefine((data, ctx) => {
    if (data.end_time <= data.start_time) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        path: ['end_time'],
        message: 'End time must be after start time',
      });
    }
  });

export const updateEventSchema = z
  .object({
    title: optionalString,
    image: optionalFileSchema.nullable(),
    category: eventTypeSchema.optional(),
    date: optionalDate,
    start_time: optionalDate,
    end_time: optionalDate,
    location: optionalString,
    event_owner: optionalString,
    description: optionalString,
    member_ids: z.array(z.string().uuid()).optional(),
  })
  .refine((data) => Object.keys(data).length > 0, {
    message: 'At least one field must be provided',
  })
  .superRefine((data, ctx) => {
    if (data.start_time && data.end_time && data.end_time <= data.start_time) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        path: ['end_time'],
        message: 'End time must be after start time',
      });
    }
  });

export const eventFilterSchema = z.object({
  category: eventTypeSchema.optional(),
  search: z.string().trim().optional(),
  from: optionalDate,
  to: optionalDate,
  page: z.preprocess((value) => {
    if (value === undefined || value === null || value === '') return 1;
    const parsed = Number(value);
    return Number.isNaN(parsed) ? value : parsed;
  }, z.number().int().min(1).default(1)),
  limit: z.preprocess((value) => {
    if (value === undefined || value === null || value === '') return 10;
    const parsed = Number(value);
    return Number.isNaN(parsed) ? value : parsed;
  }, z.number().int().min(1).max(100).default(10)),
});

export const eventResponseSchema = z.object({
  id: z.string().uuid().optional(),
  title: z.string().optional(),
  image: z.any().optional(),
  category: eventTypeSchema.optional(),
  date: z
    .date()
    .transform((date) => date.toISOString())
    .optional(),
  start_time: z
    .date()
    .transform((date) => date.toISOString())
    .optional(),
  end_time: z
    .date()
    .transform((date) => date.toISOString())
    .optional(),
  location: defaultTransformSchema,
  attendees: z.number().optional(),
  event_owner: defaultTransformSchema,
  description: defaultTransformSchema,
  members: z.array(eventMemberSchema).optional(),
  created_at: dateTransformSchema,
  updated_at: dateTransformSchema,
});

export const eventsResponseSchema = z.array(eventResponseSchema);

export type createEventDto = z.infer<typeof createEventSchema>;
export type updateEventDto = z.infer<typeof updateEventSchema>;
export type eventFilterDto = z.infer<typeof eventFilterSchema>;
export type eventResponseDto = z.infer<typeof eventResponseSchema>;
export type eventsResponseDto = z.infer<typeof eventsResponseSchema>;
