import { z } from 'zod'

/** Coerce empty strings to undefined — solves HTML form inputs sending '' for blank optional fields */
function opt<T extends z.ZodTypeAny>(schema: T) {
  return z.preprocess((v) => (v === '' ? undefined : v), schema.optional())
}

// --- Enums ---

export const LessonFormat = z.enum(['private', 'group'])
export type LessonFormat = z.infer<typeof LessonFormat>

// --- Instructor schemas ---

export const InstructorCreateSchema = z.object({
  userId: opt(z.string().uuid()),
  displayName: z.string().min(1).max(255),
  bio: opt(z.string()),
  instruments: z.array(z.string()).optional(),
})
export type InstructorCreateInput = z.infer<typeof InstructorCreateSchema>

export const InstructorUpdateSchema = InstructorCreateSchema.partial()
export type InstructorUpdateInput = z.infer<typeof InstructorUpdateSchema>

// --- Lesson Type schemas ---

export const LessonTypeCreateSchema = z.object({
  name: z.string().min(1).max(255),
  instrument: opt(z.string().max(100)),
  durationMinutes: z.coerce.number().int().min(5).max(480),
  lessonFormat: LessonFormat.default('private'),
  rateWeekly: opt(z.coerce.number().min(0)),
  rateMonthly: opt(z.coerce.number().min(0)),
  rateQuarterly: opt(z.coerce.number().min(0)),
})
export type LessonTypeCreateInput = z.infer<typeof LessonTypeCreateSchema>

export const LessonTypeUpdateSchema = LessonTypeCreateSchema.partial()
export type LessonTypeUpdateInput = z.infer<typeof LessonTypeUpdateSchema>

// --- Schedule Slot schemas ---

export const ScheduleSlotCreateSchema = z.object({
  instructorId: z.string().uuid(),
  lessonTypeId: z.string().uuid(),
  dayOfWeek: z.coerce.number().int().min(0).max(6),
  startTime: z.string().regex(/^\d{2}:\d{2}$/, 'Must be HH:MM format'),
  room: opt(z.string().max(100)),
  maxStudents: z.coerce.number().int().min(1).default(1),
  rateWeekly: opt(z.coerce.number().min(0)),
  rateMonthly: opt(z.coerce.number().min(0)),
  rateQuarterly: opt(z.coerce.number().min(0)),
})
export type ScheduleSlotCreateInput = z.infer<typeof ScheduleSlotCreateSchema>

export const ScheduleSlotUpdateSchema = ScheduleSlotCreateSchema.partial()
export type ScheduleSlotUpdateInput = z.infer<typeof ScheduleSlotUpdateSchema>

// --- Enrollment schemas ---

export const EnrollmentStatus = z.enum(['active', 'paused', 'cancelled', 'completed'])
export type EnrollmentStatus = z.infer<typeof EnrollmentStatus>

export const EnrollmentCreateSchema = z.object({
  memberId: z.string().uuid(),
  accountId: z.string().uuid(),
  scheduleSlotId: z.string().uuid(),
  instructorId: z.string().uuid(),
  startDate: z.string().min(1),
  endDate: opt(z.string()),
  rate: opt(z.coerce.number().min(0)),
  billingInterval: opt(z.coerce.number().int().min(1)),
  billingUnit: opt(z.enum(['day', 'week', 'month', 'quarter', 'year'])),
  notes: opt(z.string()),
})
export type EnrollmentCreateInput = z.infer<typeof EnrollmentCreateSchema>

export const EnrollmentUpdateSchema = EnrollmentCreateSchema.omit({
  memberId: true,
  accountId: true,
  scheduleSlotId: true,
  instructorId: true,
}).partial()
export type EnrollmentUpdateInput = z.infer<typeof EnrollmentUpdateSchema>

export const EnrollmentStatusUpdateSchema = z.object({
  status: EnrollmentStatus,
})
export type EnrollmentStatusUpdateInput = z.infer<typeof EnrollmentStatusUpdateSchema>

// --- Lesson Session schemas ---

export const LessonSessionStatus = z.enum(['scheduled', 'attended', 'missed', 'makeup', 'cancelled'])
export type LessonSessionStatus = z.infer<typeof LessonSessionStatus>

export const LessonSessionStatusUpdateSchema = z.object({
  status: LessonSessionStatus,
})
export type LessonSessionStatusUpdateInput = z.infer<typeof LessonSessionStatusUpdateSchema>

export const LessonSessionNotesSchema = z.object({
  instructorNotes: opt(z.string()),
  memberNotes: opt(z.string()),
  homeworkAssigned: opt(z.string()),
  nextLessonGoals: opt(z.string()),
  topicsCovered: z.array(z.string()).optional(),
})
export type LessonSessionNotesInput = z.infer<typeof LessonSessionNotesSchema>

export const LessonSessionUpdateSchema = z.object({
  actualStartTime: opt(z.string().regex(/^\d{2}:\d{2}$/, 'Must be HH:MM format')),
  actualEndTime: opt(z.string().regex(/^\d{2}:\d{2}$/, 'Must be HH:MM format')),
  substituteInstructorId: opt(z.string().uuid()),
})
export type LessonSessionUpdateInput = z.infer<typeof LessonSessionUpdateSchema>

// --- Instructor Blocked Date schemas ---

export const InstructorBlockedDateCreateSchema = z.object({
  startDate: z.string().min(1),
  endDate: z.string().min(1),
  reason: opt(z.string().max(255)),
})
export type InstructorBlockedDateCreateInput = z.infer<typeof InstructorBlockedDateCreateSchema>

// --- Store Closure schemas ---

export const StoreClosureCreateSchema = z.object({
  name: z.string().min(1).max(255),
  startDate: z.string().min(1),
  endDate: z.string().min(1),
})
export type StoreClosureCreateInput = z.infer<typeof StoreClosureCreateSchema>

// --- Grading Scale schemas ---

export const GradingScaleLevelInput = z.object({
  value: z.string().min(1).max(50),
  label: z.string().min(1).max(255),
  numericValue: z.coerce.number().int().min(0).max(100),
  colorHex: opt(z.string().regex(/^#[0-9A-Fa-f]{6}$/, 'Must be #RRGGBB format')),
  sortOrder: z.coerce.number().int(),
})

export const GradingScaleCreateSchema = z.object({
  name: z.string().min(1).max(255),
  description: opt(z.string()),
  isDefault: z.boolean().default(false),
  levels: z.array(GradingScaleLevelInput).min(1),
})
export type GradingScaleCreateInput = z.infer<typeof GradingScaleCreateSchema>

export const GradingScaleUpdateSchema = z.object({
  name: z.string().min(1).max(255).optional(),
  description: opt(z.string()),
  isDefault: z.boolean().optional(),
})
export type GradingScaleUpdateInput = z.infer<typeof GradingScaleUpdateSchema>

// --- Lesson Plan schemas ---

export const LessonPlanItemStatus = z.enum(['not_started', 'in_progress', 'mastered', 'skipped'])
export type LessonPlanItemStatus = z.infer<typeof LessonPlanItemStatus>

const LessonPlanItemInput = z.object({
  title: z.string().min(1).max(255),
  description: opt(z.string()),
  gradingScaleId: opt(z.string().uuid()),
  targetGradeValue: opt(z.string().max(50)),
  sortOrder: z.coerce.number().int(),
})

const LessonPlanSectionInput = z.object({
  title: z.string().min(1).max(255),
  description: opt(z.string()),
  sortOrder: z.coerce.number().int(),
  items: z.array(LessonPlanItemInput).default([]),
})

export const LessonPlanCreateSchema = z.object({
  memberId: z.string().uuid(),
  enrollmentId: z.string().uuid(),
  title: z.string().min(1).max(255),
  description: opt(z.string()),
  startedDate: opt(z.string()),
  sections: z.array(LessonPlanSectionInput).default([]),
})
export type LessonPlanCreateInput = z.infer<typeof LessonPlanCreateSchema>

export const LessonPlanUpdateSchema = z.object({
  title: z.string().min(1).max(255).optional(),
  description: opt(z.string()),
  isActive: z.boolean().optional(),
})
export type LessonPlanUpdateInput = z.infer<typeof LessonPlanUpdateSchema>

export const LessonPlanItemUpdateSchema = z.object({
  title: z.string().min(1).max(255).optional(),
  description: opt(z.string()),
  status: LessonPlanItemStatus.optional(),
  gradingScaleId: opt(z.string().uuid()),
  currentGradeValue: opt(z.string().max(50)),
  targetGradeValue: opt(z.string().max(50)),
  notes: opt(z.string()),
  sortOrder: z.coerce.number().int().optional(),
})
export type LessonPlanItemUpdateInput = z.infer<typeof LessonPlanItemUpdateSchema>

// --- Lesson Plan Template schemas ---

export const SkillLevel = z.enum(['beginner', 'intermediate', 'advanced', 'all_levels'])
export type SkillLevel = z.infer<typeof SkillLevel>

const TemplateItemInput = z.object({
  title: z.string().min(1).max(255),
  description: opt(z.string()),
  gradingScaleId: opt(z.string().uuid()),
  targetGradeValue: opt(z.string().max(50)),
  sortOrder: z.coerce.number().int(),
})

const TemplateSectionInput = z.object({
  title: z.string().min(1).max(255),
  description: opt(z.string()),
  sortOrder: z.coerce.number().int(),
  items: z.array(TemplateItemInput).default([]),
})

export const LessonPlanTemplateCreateSchema = z.object({
  name: z.string().min(1).max(255),
  description: opt(z.string()),
  instrument: opt(z.string().max(100)),
  skillLevel: SkillLevel.default('all_levels'),
  sections: z.array(TemplateSectionInput).default([]),
})
export type LessonPlanTemplateCreateInput = z.infer<typeof LessonPlanTemplateCreateSchema>

export const LessonPlanTemplateUpdateSchema = z.object({
  name: z.string().min(1).max(255).optional(),
  description: opt(z.string()),
  instrument: opt(z.string().max(100)),
  skillLevel: SkillLevel.optional(),
  isActive: z.boolean().optional(),
})
export type LessonPlanTemplateUpdateInput = z.infer<typeof LessonPlanTemplateUpdateSchema>

export const TemplateInstantiateSchema = z.object({
  memberId: z.string().uuid(),
  enrollmentId: z.string().uuid(),
  title: opt(z.string().min(1).max(255)),
})
export type TemplateInstantiateInput = z.infer<typeof TemplateInstantiateSchema>

// --- Grade History schemas ---

export const GradeCreateSchema = z.object({
  gradingScaleId: opt(z.string().uuid()),
  gradeValue: z.string().min(1).max(50),
  sessionId: opt(z.string().uuid()),
  notes: opt(z.string()),
})
export type GradeCreateInput = z.infer<typeof GradeCreateSchema>

// --- Session Plan Items schemas ---

export const SessionPlanItemsSchema = z.object({
  lessonPlanItemIds: z.array(z.string().uuid()).min(1),
})
export type SessionPlanItemsInput = z.infer<typeof SessionPlanItemsSchema>
