import { z } from "zod"

export const ElectiveCourseStatusEnum = z.enum([
  "draft",
  "open",
  "closed",
  "cancelled",
])

export const ElectiveSelectionModeEnum = z.enum(["fcfs", "lottery"])

export const CourseSelectionStatusEnum = z.enum([
  "selected",
  "enrolled",
  "waitlist",
  "dropped",
  "rejected",
])

const isValidDateString = (v: string | null | undefined): boolean => {
  if (v === null || v === undefined || v === "") return true
  const d = new Date(v)
  return !Number.isNaN(d.getTime())
}

const emptyToNull = (v: string | undefined | null): string | null =>
  v && v.length > 0 ? v : null

const optionalStringToNull = (v: string | undefined | null): string | null | undefined =>
  v === undefined ? undefined : emptyToNull(v)

export const CreateElectiveCourseSchema = z
  .object({
    name: z.string().trim().min(1).max(255),
    subjectId: z.string().trim().optional().nullable(),
    teacherId: z.string().trim().min(1),
    gradeId: z.string().trim().optional().nullable(),
    description: z.string().trim().optional().nullable(),
    capacity: z.coerce.number().int().min(1).max(500).optional(),
    classroom: z.string().trim().optional().nullable(),
    schedule: z.string().trim().optional().nullable(),
    startDate: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "开始日期格式无效"),
    endDate: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "结束日期格式无效"),
    selectionStartAt: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "选课开始时间格式无效"),
    selectionEndAt: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "选课结束时间格式无效"),
    /** 退课截止时间（P2-4 新增）：超过此时间学生不可退课 */
    dropDeadline: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "退课截止时间格式无效"),
    selectionMode: ElectiveSelectionModeEnum.optional(),
    credit: z.string().trim().optional().nullable(),
  })
  .transform((v) => ({
    name: v.name,
    subjectId: optionalStringToNull(v.subjectId) ?? null,
    teacherId: v.teacherId,
    gradeId: optionalStringToNull(v.gradeId) ?? null,
    description: optionalStringToNull(v.description),
    capacity: v.capacity ?? 30,
    classroom: optionalStringToNull(v.classroom),
    schedule: optionalStringToNull(v.schedule),
    startDate: optionalStringToNull(v.startDate),
    endDate: optionalStringToNull(v.endDate),
    selectionStartAt: optionalStringToNull(v.selectionStartAt),
    selectionEndAt: optionalStringToNull(v.selectionEndAt),
    dropDeadline: optionalStringToNull(v.dropDeadline),
    selectionMode: v.selectionMode ?? "fcfs",
    credit: v.credit && v.credit.length > 0 ? v.credit : "1.0",
  }))

export type CreateElectiveCourseInput = z.infer<typeof CreateElectiveCourseSchema>

export const UpdateElectiveCourseSchema = z
  .object({
    name: z.string().trim().min(1).max(255).optional(),
    subjectId: z.string().trim().optional().nullable(),
    teacherId: z.string().trim().min(1).optional(),
    gradeId: z.string().trim().optional().nullable(),
    description: z.string().trim().optional().nullable(),
    capacity: z.coerce.number().int().min(1).max(500).optional(),
    classroom: z.string().trim().optional().nullable(),
    schedule: z.string().trim().optional().nullable(),
    startDate: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "开始日期格式无效"),
    endDate: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "结束日期格式无效"),
    selectionStartAt: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "选课开始时间格式无效"),
    selectionEndAt: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "选课结束时间格式无效"),
    /** 退课截止时间（P2-4 新增）：超过此时间学生不可退课 */
    dropDeadline: z
      .string()
      .trim()
      .optional()
      .nullable()
      .refine(isValidDateString, "退课截止时间格式无效"),
    status: ElectiveCourseStatusEnum.optional(),
    selectionMode: ElectiveSelectionModeEnum.optional(),
    credit: z.string().trim().optional().nullable(),
  })
  .transform((v) => ({
    ...v,
    subjectId:
      v.subjectId !== undefined ? optionalStringToNull(v.subjectId) : undefined,
    gradeId:
      v.gradeId !== undefined ? optionalStringToNull(v.gradeId) : undefined,
    description:
      v.description !== undefined
        ? optionalStringToNull(v.description)
        : undefined,
    classroom:
      v.classroom !== undefined ? optionalStringToNull(v.classroom) : undefined,
    schedule:
      v.schedule !== undefined ? optionalStringToNull(v.schedule) : undefined,
    startDate:
      v.startDate !== undefined ? optionalStringToNull(v.startDate) : undefined,
    endDate:
      v.endDate !== undefined ? optionalStringToNull(v.endDate) : undefined,
    selectionStartAt:
      v.selectionStartAt !== undefined
        ? optionalStringToNull(v.selectionStartAt)
        : undefined,
    selectionEndAt:
      v.selectionEndAt !== undefined
        ? optionalStringToNull(v.selectionEndAt)
        : undefined,
    dropDeadline:
      v.dropDeadline !== undefined
        ? optionalStringToNull(v.dropDeadline)
        : undefined,
    credit:
      v.credit !== undefined
        ? v.credit && v.credit.length > 0
          ? v.credit
          : "1.0"
        : undefined,
  }))

export type UpdateElectiveCourseInput = z.infer<typeof UpdateElectiveCourseSchema>

export const SelectCourseSchema = z.object({
  courseId: z.string().trim().min(1),
  priority: z.coerce.number().int().min(1).max(10).optional(),
})

export type SelectCourseInput = z.infer<typeof SelectCourseSchema>

export const DropCourseSchema = z.object({
  courseId: z.string().trim().min(1),
  /** 退课理由（P2-4 新增）：可选，最长 255 字符 */
  dropReason: z.string().trim().max(255).optional(),
})

export type DropCourseInput = z.infer<typeof DropCourseSchema>

export const RunLotterySchema = z.object({
  courseId: z.string().trim().min(1),
})

export type RunLotteryInput = z.infer<typeof RunLotterySchema>
