"use server" import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard" import { Permissions } from "@/shared/types/permissions" import { CreateQuestionSchema } from "./schema" import type { CreateQuestionInput } from "./schema" import type { ActionState } from "@/shared/types/action-state" import { revalidatePath } from "next/cache" import { z } from "zod" import { createQuestionWithRelations, deleteQuestionByIdRecursive, getKnowledgePointOptions, getQuestions, updateQuestionById, type GetQuestionsParams, } from "./data-access" import type { KnowledgePointOption } from "./types" /** Result type of getQuestions (data + meta) */ type QuestionsListResult = Awaited> /** Result type of getKnowledgePointOptions */ type KnowledgePointOptionsResult = KnowledgePointOption[] export async function createQuestionAction( prevState: ActionState | undefined, formData: FormData | CreateQuestionInput, ): Promise> { try { const ctx = await requirePermission(Permissions.QUESTION_CREATE) let rawInput: unknown = formData if (formData instanceof FormData) { const jsonString = formData.get("json") if (typeof jsonString === "string") { rawInput = JSON.parse(jsonString) as unknown } else { return { success: false, message: "Invalid submission format. Expected JSON." } } } const validatedFields = CreateQuestionSchema.safeParse(rawInput) if (!validatedFields.success) { return { success: false, message: "Validation failed", errors: validatedFields.error.flatten().fieldErrors, } } const input = validatedFields.data await createQuestionWithRelations(input, ctx.userId) revalidatePath("/teacher/questions") return { success: true, message: "Question created successfully", } } catch (e) { if (e instanceof PermissionDeniedError) { return { success: false, message: e.message } } if (e instanceof Error) { return { success: false, message: e.message || "Database error occurred", } } return { success: false, message: "An unexpected error occurred", } } } const UpdateQuestionSchema = z.object({ id: z.string().min(1), type: z.enum(["single_choice", "multiple_choice", "text", "judgment", "composite"]), difficulty: z.number().min(1).max(5), content: z.unknown(), knowledgePointIds: z.array(z.string()).optional(), }) export async function updateQuestionAction( prevState: ActionState | undefined, formData: FormData, ): Promise> { try { const ctx = await requirePermission(Permissions.QUESTION_UPDATE) const canEditAll = ctx.dataScope.type === "all" const jsonString = formData.get("json") if (typeof jsonString !== "string") { return { success: false, message: "Invalid submission format. Expected JSON." } } const parsed = UpdateQuestionSchema.safeParse(JSON.parse(jsonString)) if (!parsed.success) { return { success: false, message: "Validation failed", errors: parsed.error.flatten().fieldErrors, } } const { id, ...updateData } = parsed.data await updateQuestionById(id, updateData, canEditAll, ctx.userId) revalidatePath("/teacher/questions") return { success: true, message: "Question updated successfully" } } catch (e) { if (e instanceof PermissionDeniedError) { return { success: false, message: e.message } } if (e instanceof Error) { return { success: false, message: e.message } } return { success: false, message: "An unexpected error occurred" } } } export async function deleteQuestionAction( prevState: ActionState | undefined, formData: FormData, ): Promise> { try { const ctx = await requirePermission(Permissions.QUESTION_DELETE) const canDeleteAll = ctx.dataScope.type === "all" const questionId = formData.get("questionId") if (typeof questionId !== "string") { return { success: false, message: "Invalid question ID" } } await deleteQuestionByIdRecursive(questionId, canDeleteAll, ctx.userId) revalidatePath("/teacher/questions") return { success: true, message: "Question deleted successfully" } } catch (e) { if (e instanceof PermissionDeniedError) { return { success: false, message: e.message } } if (e instanceof Error) { return { success: false, message: e.message } } return { success: false, message: "Failed to delete question" } } } export async function getQuestionsAction( params: GetQuestionsParams, ): Promise> { try { await requirePermission(Permissions.QUESTION_READ) const data = await getQuestions(params) return { success: true, data } } catch (e) { if (e instanceof PermissionDeniedError) { return { success: false, message: e.message } } const message = e instanceof Error ? e.message : "Failed to fetch questions" return { success: false, message } } } export async function getKnowledgePointOptionsAction(): Promise< ActionState > { try { await requirePermission(Permissions.QUESTION_READ) const data = await getKnowledgePointOptions() return { success: true, data } } catch (e) { if (e instanceof PermissionDeniedError) { return { success: false, message: e.message } } const message = e instanceof Error ? e.message : "Failed to fetch knowledge point options" return { success: false, message } } }