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

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

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

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

const requiredName = (label: string) =>
  z
    .string()
    .trim()
    .min(2, { message: `${label} must be at least 2 characters long` });

const passwordSchema = z
  .string()
  .min(6, { message: 'Password must be at least 6 characters long' })
  .regex(/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d@$!%*#?&]{6,}$/, {
    message: 'Password must contain at least one letter and one number',
  });

const genderSchema = z.enum(['male', 'female', 'others']);
const memberStatusSchema = z.enum([
  'active',
  'deactivated',
  'terminated',
  'deceased',
  'resigned',
  'deleted',
]);

const maritalStatusSchema = z.enum([
  'single',
  'married',
  'divorced',
  'widowed',
]);

export const signinMemberSchema = z
  .object({
    email: z.email({ message: 'Invalid email address' }).optional(),
    employee_id: z.string().trim().optional(),
    password: z.string({ message: 'Password is required' }),
    device_id: z.string().trim().optional(),
    device_name: z.string().trim().optional(),
  })
  .refine((data) => data.employee_id || data.email, {
    message: 'Either username or email must be provided',
  });

export const filterMembersSchema = z.object({
  status: memberStatusSchema.optional(),
  search: z.string().trim().optional(),
  department: z.string().trim().optional(),
  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)),
  attention: z.preprocess((value) => {
    if (typeof value === 'boolean') return value;
    if (typeof value === 'string') {
      const normalized = value.trim().toLowerCase();
      if (normalized === 'true') return true;
      if (normalized === 'false') return false;
    }
    return undefined;
  }, z.boolean().optional()),
  data_scope: z.enum(['own', 'all']).optional(),
});

// Work Experiences Schema
export const createWorkExperienceSchema = z.object({
  company: z.string().trim().min(1, { message: 'Company name is required' }),
  position: z.string().trim().min(1, { message: 'Position is required' }),
  start_date: z.coerce.date({ message: 'Start date is required' }),
  end_date: optionalDate,
  description: optionalString,
  relevant: z.boolean().optional().default(false),
});

export const workExperienceResponseSchema = z.object({
  id: z.string().uuid().optional(),
  company: z.string().optional(),
  position: z.string().optional(),
  start_date: z
    .date()
    .transform((date) => date.toISOString())
    .optional(),
  end_date: z
    .date()
    .transform((date) => date.toISOString())
    .optional()
    .nullable(),
  description: defaultTransformSchema,
  relevant: z.boolean().optional(),
  created_at: dateTransformSchema,
  updated_at: dateTransformSchema,
});

// Educations Schema
export const createEducationSchema = z.object({
  institution: z.string().trim().min(1, { message: 'Institution is required' }),
  degree: z.string().trim().min(1, { message: 'Degree is required' }),
  field: z.string().trim().min(1, { message: 'Field is required' }),
  start_date: z.coerce.date({ message: 'Start date is required' }),
  end_date: optionalDate,
  description: optionalString,
  relevant: z.boolean().optional().default(false),
});

export const educationResponseSchema = z.object({
  id: z.string().uuid().optional(),
  institution: z.string().optional(),
  degree: z.string().optional(),
  field: z.string().optional(),
  start_date: z
    .date()
    .transform((date) => date.toISOString())
    .optional(),
  end_date: z
    .date()
    .transform((date) => date.toISOString())
    .optional()
    .nullable(),
  description: defaultTransformSchema,
  relevant: z.boolean().optional(),
  created_at: dateTransformSchema,
  updated_at: dateTransformSchema,
});

const memberBaseSchema = z.object({
  email: z.email({ message: 'Invalid email address' }),
  work_email: optionalString,
  image: imageSchema.optional(),
  role: z.enum(['owner', 'admin', 'member']).optional(),
  access_role_id: optionalUuid,
  employee_id: z.string().trim().min(1, { message: 'Employee ID is required' }),
  nickname: optionalString,
  first_name: requiredName('First name'),
  last_name: optionalString,
  password: passwordSchema,
  about: optionalString,
  expertise: optionalString,
  work_phone: optionalString,
  phone: optionalString,
  present_address_line_one: optionalString,
  present_address_line_two: optionalString,
  present_address_city: optionalString,
  present_address_country: optionalString,
  present_address_state: optionalString,
  present_address_zip_code: optionalString,
  permanent_address_line_one: optionalString,
  permanent_address_line_two: optionalString,
  permanent_address_city: optionalString,
  permanent_address_country: optionalString,
  permanent_address_state: optionalString,
  permanent_address_zip_code: optionalString,
  father_name: optionalString,
  mother_name: optionalString,
  emargency_contact_name: optionalString,
  emargency_contact_phone: optionalString,
  emargency_contact_relation: optionalString,
  gender: genderSchema,
  date_of_birth: optionalDate,
  date_of_joining: z.date().transform((date) => date.toISOString()),
  department_id: optionalUuid,
  designation_id: optionalUuid,
  location_id: optionalUuid,
  employment_type_id: optionalUuid,
  hiring_source_id: optionalUuid,
  reporting_manager_id: optionalUuid,
  status: memberStatusSchema,
  marital_status: maritalStatusSchema,
});

export const createMemberSchema = memberBaseSchema.extend({
  access_role_id: z.string().uuid({ message: 'Access role is required' }),
  work_email: optionalString,
  nickname: optionalString,
  last_name: optionalString,
  about: optionalString,
  expertise: optionalString,
  work_phone: optionalString,
  phone: optionalString,
  present_address_line_one: optionalString,
  present_address_line_two: optionalString,
  present_address_city: optionalString,
  present_address_country: optionalString,
  present_address_state: optionalString,
  present_address_zip_code: optionalString,
  permanent_address_line_one: optionalString,
  permanent_address_line_two: optionalString,
  permanent_address_city: optionalString,
  permanent_address_country: optionalString,
  permanent_address_state: optionalString,
  permanent_address_zip_code: optionalString,
  father_name: optionalString,
  mother_name: optionalString,
  emergency_contact_name: optionalString,
  emergency_contact_phone: optionalString,
  emergency_contact_relationship: optionalString,
  gender: genderSchema.optional(),
  marital_status: maritalStatusSchema.optional(),
  date_of_birth: optionalDate,
  date_of_joining: optionalDate,
  department_id: optionalUuid,
  designation_id: optionalUuid,
  location_id: optionalUuid,
  employment_type_id: optionalUuid,
  hiring_source_id: optionalUuid,
  reporting_manager_id: optionalUuid,
  status: memberStatusSchema.optional(),
  work_experiences: z.array(createWorkExperienceSchema).optional(),
  educations: z.array(createEducationSchema).optional(),
});

export const updateMemberSchema = memberBaseSchema
  .partial()
  .extend({
    image: imageSchema.nullable().optional(),
    date_of_joining: optionalDate,
    department_id: optionalUuid,
    designation_id: optionalUuid,
    location_id: optionalUuid,
    employment_type_id: optionalUuid,
    hiring_source_id: optionalUuid,
    reporting_manager_id: optionalUuid,
    father_name: optionalString,
    mother_name: optionalString,
    emergency_contact_name: optionalString,
    emergency_contact_phone: optionalString,
    emergency_contact_relationship: optionalString,
    work_experiences: z.array(createWorkExperienceSchema).optional(),
    educations: z.array(createEducationSchema).optional(),
  })
  .refine((data) => Object.keys(data).length > 0, {
    message: 'At least one field must be provided',
  });

export const memberPreviewSchema = z.object({
  id: z.string().uuid(),
  first_name: z.string(),
  last_name: z.string().optional().nullable(),
  email: z.string().email().optional().nullable(),
  employee_id: z.string(),
  department_id: z.string().uuid().optional().nullable(),
  reporting_manager_id: z.string().uuid().optional().nullable(),
  status: memberStatusSchema,
});

export const memberResponseSchema = z.object({
  id: z.string().uuid().optional(),
  email: z.string().email().optional(),
  work_email: defaultTransformSchema,
  employee_id: z.string().optional(),
  nickname: defaultTransformSchema,
  first_name: z.string().optional(),
  last_name: defaultTransformSchema,
  about: defaultTransformSchema,
  expertise: defaultTransformSchema,
  work_phone: defaultTransformSchema,
  phone: defaultTransformSchema,
  image: imageSchema.optional(),
  role: z.enum(['owner', 'admin', 'member']).optional(),
  access_role_id: z.string().uuid().optional().nullable(),
  present_address_line_one: defaultTransformSchema,
  present_address_line_two: defaultTransformSchema,
  present_address_city: defaultTransformSchema,
  present_address_country: defaultTransformSchema,
  present_address_state: defaultTransformSchema,
  present_address_zip_code: defaultTransformSchema,
  permanent_address_line_one: defaultTransformSchema,
  permanent_address_line_two: defaultTransformSchema,
  permanent_address_city: defaultTransformSchema,
  permanent_address_country: defaultTransformSchema,
  permanent_address_state: defaultTransformSchema,
  permanent_address_zip_code: defaultTransformSchema,
  father_name: defaultTransformSchema,
  mother_name: defaultTransformSchema,
  emergency_contact_name: defaultTransformSchema,
  emergency_contact_phone: defaultTransformSchema,
  emergency_contact_relationship: defaultTransformSchema,
  gender: genderSchema.optional(),
  marital_status: maritalStatusSchema.optional(),
  date_of_birth: z
    .date()
    .transform((date) => date.toISOString())
    .optional()
    .nullable(),
  date_of_joining: optionalDate,
  department_id: z.string().uuid().optional().nullable(),
  designation_id: z.string().uuid().optional().nullable(),
  location_id: z.string().uuid().optional().nullable(),
  employment_type_id: z.string().uuid().optional().nullable(),
  hiring_source_id: z.string().uuid().optional().nullable(),
  reporting_manager_id: z.string().uuid().optional().nullable(),
  status: memberStatusSchema.optional(),
  department: z
    .object({
      id: z.string().uuid(),
      name: z.string(),
    })
    .optional()
    .nullable(),
  designation: z
    .object({
      id: z.string().uuid(),
      name: z.string(),
    })
    .optional()
    .nullable(),
  location: z
    .object({
      id: z.string().uuid(),
      name: z.string(),
    })
    .optional()
    .nullable(),
  employment_type: z
    .object({
      id: z.string().uuid(),
      name: z.string(),
    })
    .optional()
    .nullable(),
  hiring_source: z
    .object({
      id: z.string().uuid(),
      name: z.string(),
    })
    .optional()
    .nullable(),
  work_experiences: z.array(workExperienceResponseSchema).optional(),
  educations: z.array(educationResponseSchema).optional(),
  created_at: dateTransformSchema,
  updated_at: dateTransformSchema,
  token: z.string().optional(),
});

export const membersResponseSchema = z.array(memberResponseSchema);

export const memberListResponseSchema = memberResponseSchema.extend({
  attendance_percentage: z.number().optional(),
  total_leave: z.number().optional(),
  leave_balance: z.number().optional(),
  total_working_days: z.number().optional(),
  total_working_hours: z.number().optional(),
  assigned_leave: z.number().optional(),
});

export const memberListResponsesSchema = z.array(memberListResponseSchema);

export const memberOptionSchema = z.object({
  id: z.string().uuid(),
  first_name: z.string(),
  last_name: z.string().optional().nullable(),
  email: z.string().email().optional().nullable(),
  image: imageSchema.optional(),
  employee_id: z.string(),
  department_id: z.string().uuid().optional().nullable(),
  status: memberStatusSchema,
  role: z.string().optional(),
  access_token: z.string().optional(),
});

export const memberOptionsResponseSchema = z.array(memberOptionSchema);

export type signinMemberDto = z.infer<typeof signinMemberSchema>;
export type filterMembersDto = z.infer<typeof filterMembersSchema>;
export type createMemberDto = z.infer<typeof createMemberSchema>;
export type updateMemberDto = z.infer<typeof updateMemberSchema>;
export type memberResponseDto = z.infer<typeof memberResponseSchema>;
export type membersResponseDto = z.infer<typeof membersResponseSchema>;
export type memberListResponseDto = z.infer<typeof memberListResponseSchema>;
export type memberListResponsesDto = z.infer<typeof memberListResponsesSchema>;
export type memberPreviewDto = z.infer<typeof memberPreviewSchema>;
export type memberOptionDto = z.infer<typeof memberOptionSchema>;
export type memberOptionsResponseDto = z.infer<
  typeof memberOptionsResponseSchema
>;
export type createWorkExperienceDto = z.infer<
  typeof createWorkExperienceSchema
>;
export type workExperienceResponseDto = z.infer<
  typeof workExperienceResponseSchema
>;
export type createEducationDto = z.infer<typeof createEducationSchema>;
export type educationResponseDto = z.infer<typeof educationResponseSchema>;
