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 optionalFileSchema = z.any().optional();

const jobPostingStatusSchema = z.enum(['draft', 'published', 'closed']);

const jobApplicationStatusSchema = z.enum([
  'applied',
  'screening',
  'interview',
  'offer',
  'rejected',
  'hired',
  'archived',
]);

const paginationSchema = z.object({
  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)),
  search: optionalString,
});

export const createJobPostingSchema = z.object({
  title: z.string().trim().min(1, { message: 'Title is required' }),
  slug: z.string().trim().min(1, { message: 'Slug is required' }),
  short_description: optionalString,
  salary_range: optionalString,
  location: optionalString,
  job_type: optionalString,
  experience: optionalString,
  department_id: optionalUuid,
  deadline: optionalDate,
  vacancy_count: z.coerce.number().int().min(1).optional(),
  role_overview: z.union([z.string(), z.array(z.string())]).optional(),
  basics_benefits: z.array(z.string()).optional(),
  what_youll_do: z.array(z.string()).optional(),
  what_were_looking_for: z.array(z.string()).optional(),
  banner_image: imageSchema.nullable().optional(),
  icon_image: imageSchema.nullable().optional(),
  categories: z.array(z.string()).optional(),
  tags: z.array(z.string()).optional(),
  status: jobPostingStatusSchema.optional(),
});

export const updateJobPostingSchema = createJobPostingSchema.partial().refine(
  (data) => Object.keys(data).length > 0,
  { message: 'At least one field must be provided' },
);

export const jobPostingFilterSchema = paginationSchema.extend({
  status: jobPostingStatusSchema.optional(),
  department_id: optionalUuid,
  sort: z.enum(['newest', 'oldest', 'title']).optional(),
});

export const createJobApplicationSchema = z.object({
  job_posting_id: z.string().uuid({ message: 'Job posting is required' }),
  full_name: z.string().trim().min(1, { message: 'Full name is required' }),
  email: z.string().email({ message: 'Valid email is required' }),
  phone: optionalString,
  location: optionalString,
  photo_url: imageSchema.nullable().optional(),
  experience_years: z.coerce.number().int().min(0).optional(),
  resume: optionalFileSchema,
  skills: z.array(z.string()).optional(),
  work_history: z.array(z.record(z.string(), z.any())).optional(),
  notes: optionalString,
  source: z.enum(['public_form', 'public_api', 'manual']).optional(),
  status: jobApplicationStatusSchema.optional(),
  template_id: optionalString,
  start_date: optionalDate,
});

export const updateJobApplicationSchema = z
  .object({
    full_name: optionalString,
    email: z.string().email().optional(),
    phone: optionalString,
    location: optionalString,
    photo_url: imageSchema.nullable().optional(),
    experience_years: z.coerce.number().int().min(0).optional(),
    resume: optionalFileSchema,
    skills: z.array(z.string()).optional(),
    work_history: z.array(z.record(z.string(), z.any())).optional(),
    notes: optionalString,
    status: jobApplicationStatusSchema.optional(),
    interview_at: optionalDate,
    offer_status: optionalString,
    start_date: optionalDate,
    template_id: optionalString,
  })
  .refine((data) => Object.keys(data).length > 0, {
    message: 'At least one field must be provided',
  });

export const updateApplicationStatusSchema = z.object({
  status: jobApplicationStatusSchema,
  interview_at: optionalDate,
  offer_status: optionalString,
  start_date: optionalDate,
  template_id: optionalString,
});

export const bulkUpdateApplicationStatusSchema = z.object({
  ids: z.array(z.string().uuid()).min(1),
  status: jobApplicationStatusSchema,
});

export const jobApplicationFilterSchema = paginationSchema.extend({
  job_posting_id: optionalUuid,
  status: jobApplicationStatusSchema.optional(),
  source: z.enum(['public_form', 'public_api', 'manual']).optional(),
  start_date: optionalDate,
  end_date: optionalDate,
  sort: z.enum(['newest', 'oldest', 'name']).optional(),
  include_terminal: z.preprocess((value) => {
    if (value === 'true' || value === true) return true;
    if (value === 'false' || value === false) return false;
    return undefined;
  }, z.boolean().optional()),
});

export const createRecruitmentTaskSchema = z.object({
  application_id: z
    .preprocess((val) => {
      if (
        val === "00000000-0000-0000-0000-000000000000" ||
        val === "" ||
        val === null ||
        val === undefined
      )
        return null;
      return val;
    }, z.string().uuid().nullable().optional())
    .optional(),
  title: z.string().trim().min(1),
  description: optionalString,
  due_date: optionalDate,
  files: z.array(z.any()).optional(),
});

export const updateRecruitmentTaskSchema = createRecruitmentTaskSchema.partial();

export const assignRecruitmentTasksSchema = z.object({
  task_id: z.string().uuid(),
  application_ids: z.array(z.string().uuid()).min(1),
});

export const recruitmentTaskFilterSchema = paginationSchema.extend({
  application_id: optionalUuid,
  status: z.enum(['pending', 'submitted', 'reviewed']).optional(),
});

export const submitRecruitmentTaskSchema = z.object({
  text: optionalString,
  files: z.array(z.any()).optional(),
});

export const publicApplySchema = z.object({
  full_name: z.string().trim().min(1),
  email: z.string().email(),
  phone: optionalString,
  location: optionalString,
  experience_years: z.coerce.number().int().min(0).optional(),
  resume: optionalFileSchema,
  skills: z.array(z.string()).optional(),
  work_history: z.array(z.record(z.string(), z.any())).optional(),
});

export const createTenantApiKeySchema = z.object({
  name: z.string().trim().min(1),
});

export const jobPostingResponseSchema = z.object({
  id: z.string().uuid(),
  title: z.string(),
  slug: z.string(),
  short_description: defaultTransformSchema,
  salary_range: defaultTransformSchema,
  location: defaultTransformSchema,
  job_type: defaultTransformSchema,
  experience: defaultTransformSchema,
  department_id: z.string().uuid().nullable().optional(),
  deadline: dateTransformSchema.nullable().optional(),
  vacancy_count: z.number(),
  role_overview: z.any().optional(),
  basics_benefits: z.any().optional(),
  what_youll_do: z.any().optional(),
  what_were_looking_for: z.any().optional(),
  banner_image: imageSchema.nullable().optional(),
  icon_image: imageSchema.nullable().optional(),
  categories: z.any().optional(),
  tags: z.any().optional(),
  status: jobPostingStatusSchema,
  record_status: z.enum(['active', 'inactive', 'deleted']).optional(),
  owner_id: z.string().uuid(),
  created_at: dateTransformSchema,
  updated_at: dateTransformSchema,
  department: z
    .object({
      id: z.string().uuid(),
      name: z.string(),
    })
    .nullable()
    .optional(),
  owner: z
    .object({
      id: z.string().uuid(),
      slug: z.string().nullable(),
      name: z.string(),
    })
    .optional(),
});

export type createJobPostingDto = z.infer<typeof createJobPostingSchema>;
export type updateJobPostingDto = z.infer<typeof updateJobPostingSchema>;
export type jobPostingFilterDto = z.infer<typeof jobPostingFilterSchema>;
export type createJobApplicationDto = z.infer<typeof createJobApplicationSchema>;
export type updateJobApplicationDto = z.infer<typeof updateJobApplicationSchema>;
export type updateApplicationStatusDto = z.infer<
  typeof updateApplicationStatusSchema
>;
export type bulkUpdateApplicationStatusDto = z.infer<
  typeof bulkUpdateApplicationStatusSchema
>;
export type jobApplicationFilterDto = z.infer<typeof jobApplicationFilterSchema>;
export type createRecruitmentTaskDto = z.infer<typeof createRecruitmentTaskSchema>;
export type updateRecruitmentTaskDto = z.infer<typeof updateRecruitmentTaskSchema>;
export type assignRecruitmentTasksDto = z.infer<typeof assignRecruitmentTasksSchema>;
export type recruitmentTaskFilterDto = z.infer<
  typeof recruitmentTaskFilterSchema
>;
export type submitRecruitmentTaskDto = z.infer<
  typeof submitRecruitmentTaskSchema
>;
export type publicApplyDto = z.infer<typeof publicApplySchema>;
export const publicApiApplySchema = publicApplySchema.extend({
  job_posting_id: z.string().uuid({ message: 'Job posting is required' }),
});
export type publicApiApplyDto = z.infer<typeof publicApiApplySchema>;
export type createTenantApiKeyDto = z.infer<typeof createTenantApiKeySchema>;

export const scheduleInterviewSchema = z.object({
  application_ids: z
    .array(z.string().uuid())
    .min(1, { message: 'At least one candidate is required' }),
  subject: z.string().trim().min(1, { message: 'Subject is required' }),
  interview_date: z
    .string()
    .trim()
    .min(1, { message: 'Interview date is required' }),
  interview_time: z
    .string()
    .trim()
    .min(1, { message: 'Interview time is required' }),
  timezone: optionalString,
  interview_type: optionalString,
  platform_name: optionalString,
  duration: optionalString,
  meeting_link: optionalString,
  interviewers: z.array(z.string()).optional(),
  instructions: optionalString,
  send_email: z.boolean().optional(),
});

export type scheduleInterviewDto = z.infer<typeof scheduleInterviewSchema>;

export const cancelInterviewSchema = z.object({
  application_ids: z
    .array(z.string().uuid())
    .min(1, { message: 'At least one candidate is required' }),
  send_email: z.boolean().optional(),
  reason: optionalString,
});

export type cancelInterviewDto = z.infer<typeof cancelInterviewSchema>;


