import { z } from "zod";

export const subjectSchema = z.object({
  id: z.coerce.number().optional(),
  name: z.string().min(1, { message: "Subject name is required!" }),
  teachers: z.array(z.string()), //teacher ids
  schoolId: z.string(),
});

export type SubjectSchema = z.infer<typeof subjectSchema>;

export const classSchema = z.object({
  id: z.coerce.number().optional(),
  name: z.string().min(1, { message: "Subject name is required!" }),
  capacity: z.coerce.number().min(1, { message: "Capacity name is required!" }),
  gradeId: z.coerce.number().min(1, { message: "Grade name is required!" }),
  supervisorId: z.coerce.string().optional(),
  schoolId: z.string(),
});

export type ClassSchema = z.infer<typeof classSchema>;

export const teacherSchema = z.object({
  id: z.string().optional(),
  username: z
    .string()
    .min(3, { message: "Username must be at least 3 characters long!" })
    .max(20, { message: "Username must be at most 20 characters long!" }),
  password: z
    .string()
    .min(8, { message: "Password must be at least 8 characters long!" })
    .optional()
    .or(z.literal("")),
  name: z.string().min(1, { message: "First name is required!" }),
  surname: z.string().min(1, { message: "Last name is required!" }),
  email: z
    .string()
    .email({ message: "Invalid email address!" })
    .optional()
    .or(z.literal("")),
  phone: z.string().optional(),
  address: z.string(),
  img: z.string().optional(),
  bloodType: z.string().min(1, { message: "Blood Type is required!" }),
  birthday: z.coerce.date({ message: "Birthday is required!" }),
  sex: z.enum(["MALE", "FEMALE"], { message: "Sex is required!" }),
  subjects: z.array(z.string()).optional(), // subject ids
});

export type TeacherSchema = z.infer<typeof teacherSchema>;

export const studentSchema = z.object({
  id: z.string().optional(),
  username: z
    .string()
    .min(3, { message: "Username must be at least 3 characters long!" })
    .max(20, { message: "Username must be at most 20 characters long!" }),
  password: z
    .string()
    .min(8, { message: "Password must be at least 8 characters long!" })
    .optional()
    .or(z.literal("")),
  name: z.string().min(1, { message: "First name is required!" }),
  surname: z.string().min(1, { message: "Last name is required!" }),
  email: z
    .string()
    .email({ message: "Invalid email address!" })
    .optional()
    .or(z.literal("")),
  phone: z.string().optional(),
  address: z.string(),
  img: z.string().optional(),
  bloodType: z.string().min(1, { message: "Blood Type is required!" }),
  birthday: z.coerce.date({ message: "Birthday is required!" }),
  sex: z.enum(["MALE", "FEMALE"], { message: "Sex is required!" }),
  gradeId: z.coerce.number().min(1, { message: "Grade is required!" }),
  classIds: z.array(z.coerce.number()).min(1, { message: "At least one class is required!" }),
  parentId: z.string().min(1, { message: "Parent Id is required!" }),
  schoolId: z.string(),
});

export type StudentSchema = z.infer<typeof studentSchema>;

export const examSchema = z.object({
  id: z.coerce.number().optional(),
  title: z.string().min(1, { message: "Title name is required!" }),
  startTime: z.coerce.date({ message: "Start time is required!" }),
  endTime: z.coerce.date({ message: "End time is required!" }),
  lessonId: z.coerce.number({ message: "Lesson is required!" }),
  schoolId: z.string(),
});

export type ExamSchema = z.infer<typeof examSchema>;

export const lessonSchema = z.object({
  id: z.coerce.number().optional(),
  name: z.string().min(1, { message: "Lesson name is required!" }),
  startTime: z.coerce.date({ message: "Start time is required!" }),
  endTime: z.coerce.date({ message: "End time is required!" }),
  subjectId: z.coerce.number({ message: "Subject is required!" }),
  classId: z.coerce.number({ message: "Class is required!" }),
  teacherId: z.string({ message: "Teacher is required!" }),
  schoolId: z.string(),
});

export type LessonSchema = z.infer<typeof lessonSchema>;

export const assignmentSchema = z.object({
  id: z.coerce.number().optional(),
  title: z.string().min(1, { message: "Assignment title is required!" }),
  startDate: z.coerce.date({ message: "Start date is required!" }),
  dueDate: z.coerce.date({ message: "Due date is required!" }),
  lessonId: z.coerce.number({ message: "Lesson is required!" }),
  schoolId: z.string(),
});

export type AssignmentSchema = z.infer<typeof assignmentSchema>;

export const resultSchema = z.object({
  id: z.coerce.number().optional(),
  score: z.coerce.number().min(0).max(100, { message: "Score must be between 0 and 100!" }),
  studentId: z.string({ message: "Student is required!" }),
  examId: z.coerce.number().optional(),
  assignmentId: z.coerce.number().optional(),
  schoolId: z.string(),
}).refine(data => data.examId || data.assignmentId, {
  message: "Either Exam or Assignment is required",
  path: ["examId"],
});

export type ResultSchema = z.infer<typeof resultSchema>;

export const eventSchema = z.object({
  id: z.coerce.number().optional(),
  title: z.string().min(1, { message: "Title is required!" }),
  description: z.string().min(1, { message: "Description is required!" }),
  startTime: z.coerce.date({ message: "Start time is required!" }),
  endTime: z.coerce.date({ message: "End time is required!" }),
  classId: z.coerce.number().optional(),
  schoolId: z.string(),
});

export type EventSchema = z.infer<typeof eventSchema>;

export const announcementSchema = z.object({
  id: z.coerce.number().optional(),
  title: z.string().min(1, { message: "Title is required!" }),
  description: z.string().min(1, { message: "Description is required!" }),
  date: z.coerce.date({ message: "Date is required!" }),
  classId: z.coerce.number().optional(),
  schoolId: z.string(),
});

export type AnnouncementSchema = z.infer<typeof announcementSchema>;

export const termSchema = z.object({
  id: z.coerce.number().optional(),
  name: z.string().min(1, { message: "Term name is required!" }),
  startDate: z.coerce.date({ message: "Start date is required!" }),
  endDate: z.coerce.date({ message: "End date is required!" }),
  schoolId: z.string(),
  academicYearId: z.coerce.number().optional(),
});

export type TermSchema = z.infer<typeof termSchema>;

export const holidaySchema = z.object({
  id: z.coerce.number().optional(),
  name: z.string().min(1, { message: "Holiday name is required!" }),
  startDate: z.coerce.date({ message: "Start date is required!" }),
  endDate: z.coerce.date({ message: "End date is required!" }),
  schoolId: z.string(),
  academicYearId: z.coerce.number().optional(),
});

export type HolidaySchema = z.infer<typeof holidaySchema>;

export const schoolTimetableSlotSchema = z.object({
  id: z.coerce.number().optional(),
  name: z.string().min(1, { message: "Slot name is required!" }),
  startTime: z.string().min(1, { message: "Start time is required!" }),
  endTime: z.string().min(1, { message: "End time is required!" }),
  isTeachingSlot: z.boolean().default(true),
  schoolId: z.string(),
  schoolTimetableId: z.coerce.number().optional(),
  position: z.coerce.number().optional(),
});

export type SchoolTimetableSlotSchema = z.infer<typeof schoolTimetableSlotSchema>;

export const timetableTemplateSchema = z.object({
  id: z.coerce.number().optional(),
  name: z.string().min(1, { message: "Template name is required!" }),
  teacherId: z.string().min(1, { message: "Teacher is required!" }),
  schoolId: z.string(),
  schoolTimetableId: z.coerce.number().optional(),
});

export type TimetableTemplateSchema = z.infer<typeof timetableTemplateSchema>;

export const timetableEntrySchema = z.object({
  id: z.coerce.number().optional(),
  timetableTemplateId: z.coerce.number({ message: "Template ID is required!" }),
  teacherTimetableTemplateId: z.coerce.number().optional(),
  schoolTimetableSlotId: z.coerce.number({ message: "Time Slot is required!" }),
  classId: z.coerce.number({ message: "Class is required!" }),
  subjectId: z.coerce.number({ message: "Subject is required!" }),
  dayOfWeek: z.coerce.number().min(1).max(7, { message: "Invalid day of week!" }),
});

export type TimetableEntrySchema = z.infer<typeof timetableEntrySchema>;
