import z from 'zod';
import { isValidIanaTimezone } from '../../common/timezone/timezone.util';
import { defaultTransformSchema, imageSchema } from '../shared/shared.dto';

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

const timezoneSchema = z
  .string()
  .min(1)
  .refine((value) => isValidIanaTimezone(value), {
    message: 'Timezone must be a valid IANA timezone identifier',
  });

export const updateWorkScheduleSchema = z.object({
  working_days: z
    .array(
      z.enum([
        'monday',
        'tuesday',
        'wednesday',
        'thursday',
        'friday',
        'saturday',
        'sunday',
      ]),
    )
    .optional(),

  working_days_per_week: z.number().optional(),
  working_hours_per_day: z.number().optional(),
  office_start_time: optionalDate,
  office_end_time: optionalDate,
  half_day_min_time: z.number().optional(),
  half_day_max_time: z.number().optional(),
  timezone: timezoneSchema.optional(),
  monthly_correction_limit: z.number().int().min(0).max(31).optional(),
});

export const updateCompanyInfoSchema = z.object({
  name: z.string().optional(),
  company_code: z.string().optional(),
  email: z.string().email().optional(),
  phone: z.string().optional(),
  address: z.string().optional(),
  website: z.string().optional(),
  logo: imageSchema.optional(),
  description: z.string().optional(),
  founded_at: optionalDate,
  industry: z.string().optional(),
});

export const updataLeavePolicySchema = z.object({
  annual_leave_days: z.number().optional(),
  sick_leave_days: z.number().optional(),
  casual_leave_days: z.number().optional(),
  maternity_leave_days: z.number().optional(),
  paternity_leave_days: z.number().optional(),
  personal_leave_days: z.number().optional(),
  compensatory_leave_days: z.number().optional(),
  unpaid_leave_days: z.number().optional(),
});

export const companyInfoResponseSchema = z.object({
  id: z.string().optional(),
  name: defaultTransformSchema,
  company_code: defaultTransformSchema,
  email: defaultTransformSchema,
  phone: defaultTransformSchema,
  address: defaultTransformSchema,
  website: defaultTransformSchema,
  logo: imageSchema.nullable().optional(),
  description: defaultTransformSchema,
  founded_at: optionalDate,
  industry: defaultTransformSchema,
});

export const workScheduleResponseSchema = z.object({
  id: z.string().optional(),
  working_days: z.array(
    z.enum([
      'monday',
      'tuesday',
      'wednesday',
      'thursday',
      'friday',
      'saturday',
      'sunday',
    ]),
  ),
  working_days_per_week: z.number(),
  working_hours_per_day: z.number(),
  office_start_time: optionalDate,
  office_end_time: optionalDate,
  half_day_min_time: z.number().optional(),
  half_day_max_time: z.number().optional(),
  timezone: timezoneSchema.optional(),
  monthly_correction_limit: z.number().int().min(0).default(2),
});

export const leavePolicyResponseSchema = z.object({
  id: z.string().optional(),
  annual_leave_days: z.number(),
  sick_leave_days: z.number(),
  casual_leave_days: z.number(),
  maternity_leave_days: z.number(),
  paternity_leave_days: z.number(),
  personal_leave_days: z.number(),
  compensatory_leave_days: z.number(),
  unpaid_leave_days: z.number(),
});

const timeStringSchema = z
  .string()
  .regex(/^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/, 'Time must be in HH:mm format');

export const singleWorkDayScheduleSchema = z.object({
  id: z.string().uuid().optional(),
  day_of_week: z.number().int().min(0).max(6),
  is_active: z.boolean(),
  start_time: timeStringSchema.default('09:00'),
  end_time: timeStringSchema.default('17:00'),
  break_start: timeStringSchema.nullable().optional(),
  break_end: timeStringSchema.nullable().optional(),
  grace_period_minutes: z.number().int().min(0).max(180).default(15),
});

export const updateWorkDaySchedulesSchema = z.object({
  schedules: z.array(singleWorkDayScheduleSchema).min(1).max(7),
});

export const workDayScheduleResponseSchema = z.object({
  id: z.string().uuid(),
  owner_id: z.string(),
  day_of_week: z.number(),
  is_active: z.boolean(),
  start_time: z.string(),
  end_time: z.string(),
  break_start: z.string().nullable(),
  break_end: z.string().nullable(),
  grace_period_minutes: z.number(),
});

export const workDaySchedulesListResponseSchema = z.array(
  workDayScheduleResponseSchema,
);

export const updateAttendanceValidationSettingsSchema = z.object({
  enforce_ip_whitelist: z.boolean().optional(),
  enforce_location: z.boolean().optional(),
  location_name: z.string().trim().min(1).optional(),
  latitude: z.number().nullable().optional(),
  longitude: z.number().nullable().optional(),
  radius_meters: z.number().int().min(10).max(10000).optional(),
});

export const attendanceValidationSettingsResponseSchema = z.object({
  id: z.string().uuid().optional(),
  owner_id: z.string().optional(),
  enforce_ip_whitelist: z.boolean(),
  enforce_location: z.boolean(),
  location_name: z.string(),
  latitude: z
    .union([z.number(), z.string()])
    .transform((val) =>
      val === null || val === undefined ? null : Number(val),
    )
    .nullable()
    .optional(),
  longitude: z
    .union([z.number(), z.string()])
    .transform((val) =>
      val === null || val === undefined ? null : Number(val),
    )
    .nullable()
    .optional(),
  radius_meters: z.number(),
  created_at: optionalDate,
  updated_at: optionalDate,
});

export type UpdateWorkScheduleDto = z.infer<typeof updateWorkScheduleSchema>;
export type UpdateCompanyInfoDto = z.infer<typeof updateCompanyInfoSchema>;
export type UpdateLeavePolicyDto = z.infer<typeof updataLeavePolicySchema>;
export type CompanyInfoResponseDto = z.infer<typeof companyInfoResponseSchema>;
export type WorkScheduleResponseDto = z.infer<
  typeof workScheduleResponseSchema
>;
export type LeavePolicyResponseDto = z.infer<typeof leavePolicyResponseSchema>;
export type SingleWorkDayScheduleDto = z.infer<
  typeof singleWorkDayScheduleSchema
>;
export type UpdateWorkDaySchedulesDto = z.infer<
  typeof updateWorkDaySchedulesSchema
>;
export type WorkDayScheduleResponseDto = z.infer<
  typeof workDayScheduleResponseSchema
>;
export type UpdateAttendanceValidationSettingsDto = z.infer<
  typeof updateAttendanceValidationSettingsSchema
>;
export type AttendanceValidationSettingsResponseDto = z.infer<
  typeof attendanceValidationSettingsResponseSchema
>;


