"use server"

import { revalidatePath } from "next/cache"
import { getTranslations } from "next-intl/server"
import { requirePermission } from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"
import type { ActionState } from "@/shared/types/action-state"
import { handleActionError } from "@/shared/lib/action-utils"

import { getGradeRecordById } from "./data-access"
import {
  hasPendingAppeal,
  createGradeAppeal,
  getStudentAppeals,
  getPendingAppealsForReview,
  getAppealById,
  reviewGradeAppeal,
  withdrawGradeAppeal,
  type GradeAppeal,
  type GradeAppealWithRecord,
} from "./data-access-appeals"
import { CreateGradeAppealSchema, ReviewGradeAppealSchema } from "./schema"

/**
 * P3-7 成绩申诉 Server Actions。
 *
 * 权限模型：
 * - 学生提交/撤回/查看自己的申诉：GRADE_RECORD_READ
 * - 教师复核申诉：GRADE_RECORD_MANAGE
 *
 * 状态机：pending → approved/rejected/withdrawn
 */

/**
 * 学生提交成绩申诉。
 *
 * 校验：
 * 1. 成绩记录存在且属于当前用户（scope=owned 时 studentId=ctx.userId）
 * 2. 该成绩无 pending 申诉
 */
export async function createGradeAppealAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_READ)
    const t = await getTranslations("grades")

    const parsed = CreateGradeAppealSchema.safeParse({
      gradeRecordId: formData.get("gradeRecordId"),
      reason: formData.get("reason"),
      expectedScore: formData.get("expectedScore") || undefined,
    })

    if (!parsed.success) {
      return {
        success: false,
        message: t("action.invalidFormData"),
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    // 校验成绩归属
    const record = await getGradeRecordById(parsed.data.gradeRecordId)
    if (!record) {
      return { success: false, message: t("appeal.gradeNotFound") }
    }
    if (record.studentId !== ctx.userId) {
      return { success: false, message: t("appeal.notYourGrade") }
    }

    // 校验无 pending 申诉
    const hasPending = await hasPendingAppeal(parsed.data.gradeRecordId)
    if (hasPending) {
      return { success: false, message: t("appeal.pendingExists") }
    }

    const id = await createGradeAppeal({
      gradeRecordId: parsed.data.gradeRecordId,
      studentId: ctx.userId,
      originalScore: record.score,
      reason: parsed.data.reason,
      expectedScore: parsed.data.expectedScore,
    })

    revalidatePath("/student/grades")
    return { success: true, message: t("appeal.created"), data: id }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * 学生撤回申诉。
 */
export async function withdrawGradeAppealAction(
  appealId: string
): Promise<ActionState<{ withdrawn: true }>> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_READ)

    await withdrawGradeAppeal({ appealId, studentId: ctx.userId })

    revalidatePath("/student/grades")
    return { success: true, data: { withdrawn: true } }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * 获取学生自己的申诉列表。
 */
export async function getStudentAppealsAction(): Promise<
  ActionState<GradeAppeal[]>
> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_READ)

    const appeals = await getStudentAppeals(ctx.userId)
    return { success: true, data: appeals }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * 教师复核申诉（approve/reject）。
 *
 * 若 approve 且提供 adjustedScore，会同步更新 grade_records.score。
 */
export async function reviewGradeAppealAction(
  prevState: ActionState<{ reviewed: true }> | null,
  formData: FormData
): Promise<ActionState<{ reviewed: true }>> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_MANAGE)
    const t = await getTranslations("grades")

    const parsed = ReviewGradeAppealSchema.safeParse({
      appealId: formData.get("appealId"),
      decision: formData.get("decision"),
      reviewComment: formData.get("reviewComment"),
      adjustedScore: formData.get("adjustedScore") || undefined,
    })

    if (!parsed.success) {
      return {
        success: false,
        message: t("action.invalidFormData"),
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    // 校验申诉归属：教师只能复核自己班级的申诉
    const appeal = await getAppealById(parsed.data.appealId)
    if (!appeal) {
      return { success: false, message: t("appeal.notFound") }
    }

    const scopeError = ctx.dataScope.type === "class_taught"
      ? (ctx.dataScope.classIds.includes(appeal.gradeRecordClassId) ? null : "out_of_scope")
      : ctx.dataScope.type === "all"
        ? null
        : "out_of_scope"

    if (scopeError) {
      return { success: false, message: t("appeal.outOfScope") }
    }

    await reviewGradeAppeal({
      appealId: parsed.data.appealId,
      reviewerId: ctx.userId,
      decision: parsed.data.decision,
      reviewComment: parsed.data.reviewComment,
      adjustedScore: parsed.data.adjustedScore,
    })

    revalidatePath("/teacher/grades")
    revalidatePath("/student/grades")
    return {
      success: true,
      message: parsed.data.decision === "approved"
        ? t("appeal.approved")
        : t("appeal.rejected"),
      data: { reviewed: true },
    }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * 获取教师待复核的申诉列表。
 */
export async function getPendingAppealsForReviewAction(): Promise<
  ActionState<GradeAppealWithRecord[]>
> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_MANAGE)

    // 获取教师班级范围
    const classIds =
      ctx.dataScope.type === "class_taught" ? ctx.dataScope.classIds : []

    if (ctx.dataScope.type !== "all" && classIds.length === 0) {
      return { success: true, data: [] }
    }

    const appeals = await getPendingAppealsForReview(classIds)
    return { success: true, data: appeals }
  } catch (e) {
    return handleActionError(e)
  }
}
