"use server"

import { revalidatePath } from "next/cache"
import { createId } from "@paralleldrive/cuid2"

import { requirePermission } from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"
import type { ActionState } from "@/shared/types/action-state"
import { handleActionError, safeJsonParse, safeParseDate } from "@/shared/lib/action-utils"
import { trackExamEvent } from "@/shared/lib/track-event"

import { CreateHomeworkAssignmentSchema, GradeHomeworkSchema } from "./schema"
import {
  createHomeworkAssignment,
  getActiveClassStudentIdsForHomework,
  getClassTeacherById,
  getExamWithQuestionsForHomework,
  getHomeworkSubmissionForGrading,
  getHomeworkSubmissionForPermission,
  getTeacherAssignedSubjectIds,
  gradeHomeworkAnswers,
  markHomeworkSubmitted,
  saveHomeworkAnswer,
  startHomeworkSubmission,
  batchAutoGradeSubmissions,
} from "./data-access-write"

const parseStudentIds = (raw: string): string[] => {
  return raw
    .split(/[,\n\r\t ]+/g)
    .map((s) => s.trim())
    .filter((s) => s.length > 0)
}

export async function createHomeworkAssignmentAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.HOMEWORK_CREATE)

    const targetStudentIdsJson = formData.get("targetStudentIdsJson")
    const targetStudentIdsText = formData.get("targetStudentIdsText")

    const parsed = CreateHomeworkAssignmentSchema.safeParse({
      sourceExamId: formData.get("sourceExamId"),
      classId: formData.get("classId"),
      title: formData.get("title") || undefined,
      description: formData.get("description") || undefined,
      availableAt: formData.get("availableAt") || undefined,
      dueAt: formData.get("dueAt") || undefined,
      allowLate: formData.get("allowLate") || undefined,
      lateDueAt: formData.get("lateDueAt") || undefined,
      maxAttempts: formData.get("maxAttempts") || undefined,
      publish: formData.get("publish") || undefined,
      targetStudentIds:
        typeof targetStudentIdsJson === "string" && targetStudentIdsJson.length > 0
          ? (JSON.parse(targetStudentIdsJson) as unknown)
          : typeof targetStudentIdsText === "string" && targetStudentIdsText.trim().length > 0
            ? parseStudentIds(targetStudentIdsText)
            : undefined,
    })

    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid form data",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    const input = parsed.data
    const publish = input.publish ?? true

    const classRow = await getClassTeacherById(input.classId)
    if (!classRow) return { success: false, message: "Class not found" }

    // 快速作业模式：无 sourceExamId 时创建纯文本作业（无题目）
    const isQuickAssignment = !input.sourceExamId

    let exam: Awaited<ReturnType<typeof getExamWithQuestionsForHomework>> = null
    if (!isQuickAssignment) {
      const sourceExamId = input.sourceExamId
      if (!sourceExamId) {
        return { success: false, message: "sourceExamId is required for exam mode" }
      }
      const examData = await getExamWithQuestionsForHomework(sourceExamId)
      if (!examData) return { success: false, message: "Exam not found" }
      exam = examData
    }

    if (ctx.dataScope.type !== "all" && classRow.teacherId !== ctx.userId) {
      const assignedSubjectIds = await getTeacherAssignedSubjectIds(input.classId, ctx.userId)
      if (assignedSubjectIds.length === 0) {
        return { success: false, message: "Not assigned to this class" }
      }
      if (!isQuickAssignment && exam) {
        const assignedSubjectSet = new Set(assignedSubjectIds)
        if (!exam.subjectId) {
          return { success: false, message: "Exam subject not set" }
        }
        if (!assignedSubjectSet.has(exam.subjectId)) {
          return { success: false, message: "Not assigned to this subject" }
        }
      }
    }

    const classStudentIds = await getActiveClassStudentIdsForHomework(
      input.classId,
      ctx.dataScope,
      ctx.userId,
      classRow.teacherId
    )
    const classStudentIdSet = new Set(classStudentIds)

    const targetStudentIds =
      input.targetStudentIds && input.targetStudentIds.length > 0
        ? input.targetStudentIds.filter((id) => classStudentIdSet.has(id))
        : classStudentIds

    if (publish && targetStudentIds.length === 0) {
      return { success: false, message: "No active students in this class" }
    }

    const assignmentId = createId()
    const availableAt = input.availableAt ? safeParseDate(input.availableAt, "可用时间") : null
    const dueAt = input.dueAt ? safeParseDate(input.dueAt, "截止时间") : null
    const lateDueAt = input.lateDueAt ? safeParseDate(input.lateDueAt, "迟交截止时间") : null

    await createHomeworkAssignment({
      assignmentId,
      sourceExamId: input.sourceExamId ?? null,
      title: input.title?.trim().length ? input.title.trim() : (exam?.title ?? "Untitled Assignment"),
      description: input.description ?? null,
      structure: exam?.structure ?? [],
      status: publish ? "published" : "draft",
      creatorId: ctx.userId,
      availableAt,
      dueAt,
      allowLate: input.allowLate ?? false,
      lateDueAt,
      maxAttempts: input.maxAttempts ?? 1,
      publish,
      questions: exam?.questions ?? [],
      targetStudentIds,
    })

    revalidatePath("/teacher/homework/assignments")
    revalidatePath("/teacher/homework/submissions")

    // V3-4: 埋点监控
    await trackExamEvent("homework.created", {
      userId: ctx.userId,
      targetId: assignmentId,
      properties: {
        sourceExamId: input.sourceExamId ?? null,
        classId: input.classId,
        targetStudentCount: targetStudentIds.length,
        published: publish,
      },
    })

    return { success: true, message: "Assignment created", data: assignmentId }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function startHomeworkSubmissionAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.HOMEWORK_SUBMIT)
    const assignmentId = formData.get("assignmentId")
    if (typeof assignmentId !== "string" || assignmentId.length === 0) return { success: false, message: "Missing assignmentId" }

    const result = await startHomeworkSubmission(assignmentId, ctx.userId)
    if ("error" in result) {
      return { success: false, message: result.error }
    }

    revalidatePath("/student/learning/assignments")

    return { success: true, message: "Started", data: result.submissionId }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function saveHomeworkAnswerAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.HOMEWORK_SUBMIT)
    const submissionId = formData.get("submissionId")
    const questionId = formData.get("questionId")
    const answerJson = formData.get("answerJson")
    if (typeof submissionId !== "string" || submissionId.length === 0) return { success: false, message: "Missing submissionId" }
    if (typeof questionId !== "string" || questionId.length === 0) return { success: false, message: "Missing questionId" }

    const submission = await getHomeworkSubmissionForPermission(submissionId)
    if (!submission) return { success: false, message: "Submission not found" }
    if (submission.studentId !== ctx.userId) return { success: false, message: "Unauthorized" }
    if (submission.status !== "started") return { success: false, message: "Submission is locked" }

    const payload =
      typeof answerJson === "string" && answerJson.length > 0
        ? safeJsonParse<unknown>(answerJson, "答案数据格式无效")
        : null

    await saveHomeworkAnswer(submissionId, questionId, payload)

    return { success: true, message: "Saved", data: submissionId }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function submitHomeworkAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.HOMEWORK_SUBMIT)
    const submissionId = formData.get("submissionId")
    if (typeof submissionId !== "string" || submissionId.length === 0) return { success: false, message: "Missing submissionId" }

    const submission = await getHomeworkSubmissionForPermission(submissionId)
    if (!submission) return { success: false, message: "Submission not found" }
    if (submission.studentId !== ctx.userId) return { success: false, message: "Unauthorized" }
    if (submission.status !== "started") return { success: false, message: "Already submitted" }

    const now = new Date()
    const dueAt = submission.assignment.dueAt
    const allowLate = submission.assignment.allowLate
    const lateDueAt = submission.assignment.lateDueAt

    if (dueAt && now > dueAt && !allowLate) return { success: false, message: "Past due" }
    if (allowLate && lateDueAt && now > lateDueAt) return { success: false, message: "Past late due" }

    const isLate = Boolean(dueAt && now > dueAt)

    // V3-2: 即时自动批改回写
    const { isFullyAutoGraded, totalScore } = await markHomeworkSubmitted(submissionId, isLate)

    revalidatePath("/teacher/homework/submissions")
    revalidatePath("/student/learning/assignments")

    // V3-4: 埋点监控
    await trackExamEvent("homework.submitted", {
      userId: ctx.userId,
      targetId: submissionId,
      properties: {
        isLate,
        isFullyAutoGraded,
        totalScore,
      },
    })

    return {
      success: true,
      message: isFullyAutoGraded ? "Submitted and auto-graded" : "Submitted",
      data: submissionId,
    }
  } catch (e) {
    return handleActionError(e)
  }
}

export async function gradeHomeworkSubmissionAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.HOMEWORK_GRADE)

    const rawAnswersValue = formData.get("answersJson")
    const rawAnswers = typeof rawAnswersValue === "string" ? rawAnswersValue : null
    const parsed = GradeHomeworkSchema.safeParse({
      submissionId: formData.get("submissionId"),
      answers: rawAnswers ? safeJsonParse<unknown[]>(rawAnswers, "批改数据格式无效") : [],
    })

    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid grading data",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    const { submissionId, answers } = parsed.data

    // 权限二次校验：非管理员仅可批改自己创建的作业提交
    // 管理员（dataScope.type === "all"）可批改所有提交
    if (ctx.dataScope.type !== "all") {
      const submissionForGrading = await getHomeworkSubmissionForGrading(submissionId)
      if (!submissionForGrading) {
        return { success: false, message: "Submission not found" }
      }
      if (submissionForGrading.creatorId !== ctx.userId) {
        return { success: false, message: "You can only grade submissions for your own assignments" }
      }
    }

    await gradeHomeworkAnswers(
      submissionId,
      answers.map((ans) => ({
        id: ans.id,
        score: ans.score,
        feedback: ans.feedback ?? null,
      }))
    )

    revalidatePath("/teacher/homework/submissions")

    // V3-4: 埋点监控
    await trackExamEvent("homework.graded", {
      userId: ctx.userId,
      targetId: submissionId,
      properties: {
        answerCount: answers.length,
      },
    })

    return { success: true, message: "Grading saved" }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * V3-7: 批量自动批改提交
 *
 * 教师在提交列表页勾选多份提交后，一键自动批改所有客观题。
 * 仅批改选择题/判断题，主观题保持原分数。
 */
export async function batchAutoGradeSubmissionsAction(
  prevState: ActionState<{ successCount: number; failedCount: number; fullyGradedCount: number }> | null,
  formData: FormData
): Promise<ActionState<{ successCount: number; failedCount: number; fullyGradedCount: number }>> {
  try {
    const ctx = await requirePermission(Permissions.HOMEWORK_GRADE)

    const rawSubmissionIds = formData.get("submissionIds")
    const submissionIdsJson = typeof rawSubmissionIds === "string" ? rawSubmissionIds : "[]"
    const submissionIds = safeJsonParse<string[]>(submissionIdsJson, "提交 ID 列表格式无效")

    if (submissionIds.length === 0) {
      return {
        success: false,
        message: "请至少选择一份提交",
      }
    }

    // 权限校验：非管理员仅可批改自己创建的作业提交
    if (ctx.dataScope.type !== "all") {
      for (const submissionId of submissionIds) {
        const submissionForGrading = await getHomeworkSubmissionForGrading(submissionId)
        if (!submissionForGrading) {
          return { success: false, message: `提交不存在: ${submissionId}` }
        }
        if (submissionForGrading.creatorId !== ctx.userId) {
          return { success: false, message: "只能批改自己创建的作业提交" }
        }
      }
    }

    const results = await batchAutoGradeSubmissions(submissionIds)
    const successCount = results.filter((r) => r.success).length
    const failedCount = results.filter((r) => !r.success).length
    const fullyGradedCount = results.filter((r) => r.success && r.isFullyAutoGraded).length

    revalidatePath("/teacher/homework/submissions")
    revalidatePath("/teacher/homework/assignments")

    await trackExamEvent("homework.graded", {
      userId: ctx.userId,
      targetId: submissionIds[0] ?? "",
      properties: {
        batchCount: submissionIds.length,
        successCount,
        fullyGradedCount,
      },
    })

    return {
      success: true,
      message: `批量批改完成：成功 ${successCount} 份，失败 ${failedCount} 份，其中 ${fullyGradedCount} 份已全自动批改`,
      data: { successCount, failedCount, fullyGradedCount },
    }
  } catch (e) {
    return handleActionError(e)
  }
}
