/**
 * 考试 Server Action 共享辅助函数（非 "use server" 文件，可导出非异步工具函数）。
 *
 * 供 actions.ts / actions-rich-editor.ts / ai-pipeline/auto-mark.ts 共同使用。
 */

import { createId } from "@paralleldrive/cuid2"
import { z } from "zod"
import type { ActionState } from "@/shared/types/action-state"
import {
  buildExamDescription,
  resolveSubjectGradeNames,
  type ExamModeConfig,
} from "./data-access"

export const getStringValue = (formData: FormData, key: string): string | undefined => {
  const value = formData.get(key)
  return typeof value === "string" ? value : undefined
}

export const getBoolValue = (formData: FormData, key: string, fallback = false): boolean => {
  const value = formData.get(key)
  if (typeof value !== "string") return fallback
  return value === "true"
}

export const parseExamModeConfig = (formData: FormData): ExamModeConfig => {
  const rawMode = getStringValue(formData, "examMode")
  const examMode: ExamModeConfig["examMode"] =
    rawMode === "timed" || rawMode === "proctored" ? rawMode : "homework"
  const rawDuration = getStringValue(formData, "durationMinutes")
  const durationMinutes = rawDuration && Number.isFinite(Number(rawDuration))
    ? Number(rawDuration)
    : null
  const rawGrace = getStringValue(formData, "lateStartGraceMinutes") ?? "0"
  const parsedGrace = Number(rawGrace)
  const lateStartGraceMinutes = Number.isFinite(parsedGrace) ? parsedGrace : 0
  return {
    examMode,
    durationMinutes,
    shuffleQuestions: getBoolValue(formData, "shuffleQuestions", false),
    allowLateStart: getBoolValue(formData, "allowLateStart", false),
    lateStartGraceMinutes,
    antiCheatEnabled: getBoolValue(formData, "antiCheatEnabled", false),
  }
}

export const failState = <T>(message: string, errors?: Record<string, string[]>): ActionState<T> => ({
  success: false,
  message,
  errors,
})

export const successState = <T>(data: T, message?: string): ActionState<T> => ({
  success: true,
  message,
  data,
})

export const invalidFormState = <T>(
  error: z.ZodError,
  options?: { fallbackMessage?: string; useFirstMessage?: boolean }
): ActionState<T> => {
  const errors = error.flatten().fieldErrors
  const fallbackMessage = options?.fallbackMessage ?? "Invalid form data"
  const useFirstMessage = options?.useFirstMessage ?? true
  const messages = Object.values(errors).flatMap((items) => items ?? [])
  const firstMessage = messages.find((msg): msg is string => typeof msg === "string" && msg.length > 0)
  return failState<T>(useFirstMessage ? (firstMessage ?? fallbackMessage) : fallbackMessage, errors)
}

export const prepareExamCreateContext = async (input: {
  subject: string
  grade: string
  difficulty: number
  totalScore: number
  durationMin: number
  scheduledAt?: string | null
}): Promise<{
  examId: string
  scheduled: string | undefined
  subjectName: string
  gradeName: string
  buildDescription: (options?: { questionCount?: number }) => string
}> => {
  const examId = createId()
  const scheduled = input.scheduledAt || undefined
  const resolvedNames = await resolveSubjectGradeNames({
    subjectId: input.subject,
    gradeId: input.grade,
  })
  const subjectName = resolvedNames.subjectName ?? input.subject
  const gradeName = resolvedNames.gradeName ?? input.grade
  const buildDescription = (options?: { questionCount?: number }) => buildExamDescription({
    subject: subjectName,
    grade: gradeName,
    difficulty: input.difficulty,
    totalScore: input.totalScore,
    durationMin: input.durationMin,
    scheduledAt: scheduled,
    questionCount: options?.questionCount,
  })
  return { examId, scheduled, subjectName, gradeName, buildDescription }
}
