"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 { trackEvent } from "@/shared/lib/track-event"

import {
  CreateElectiveCourseSchema,
  UpdateElectiveCourseSchema,
  SelectCourseSchema,
  DropCourseSchema,
  RunLotterySchema,
} from "./schema"
import {
  getElectiveCourseById,
  createElectiveCourse,
  updateElectiveCourse,
  deleteElectiveCourse,
  openSelection,
  closeSelection,
} from "./data-access"
import {
  runLottery,
  selectCourse,
  dropCourse,
  ElectiveBusinessError,
  type ElectiveErrorCode,
} from "./data-access-operations"
import { COURSE_SELECTION_STATUS_LABEL_KEYS } from "./constants"

const revalidateElectivePaths = (id?: string) => {
  revalidatePath("/admin/elective")
  revalidatePath("/teacher/elective")
  revalidatePath("/student/elective")
  revalidatePath("/parent/elective")
  if (id) {
    revalidatePath(`/admin/elective/${id}`)
    revalidatePath(`/admin/elective/${id}/edit`)
    revalidatePath(`/teacher/elective/${id}`)
    revalidatePath(`/teacher/elective/${id}/edit`)
  }
}

const requireCourseId = (formData: FormData): string => {
  const id = String(formData.get("courseId") ?? "")
  if (!id) throw new Error("Course ID is required")
  return id
}

/**
 * 将 ElectiveBusinessError 翻译为用户可见的 i18n 文案。
 * 在 catch 中调用，返回 null 表示非业务错误（交给 handleActionError）。
 */
async function translateBusinessError(
  e: unknown,
  t: Awaited<ReturnType<typeof getTranslations>>
): Promise<string | null> {
  if (e instanceof ElectiveBusinessError) {
    const code = e.code satisfies ElectiveErrorCode
    if (e.params) {
      return t(`errors.${code}`, e.params)
    }
    return t(`errors.${code}`)
  }
  return null
}

/**
 * 校验当前用户对课程的管理权限（资源归属校验）。
 * - admin（scope=all）：直接放行
 * - teacher（其他 scope）：必须为课程的授课教师
 */
async function assertCourseOwnership(
  courseId: string,
  ctx: Awaited<ReturnType<typeof requirePermission>>
): Promise<{ ok: boolean; message?: string }> {
  const t = await getTranslations("elective")
  if (ctx.dataScope.type === "all") return { ok: true }
  const course = await getElectiveCourseById(courseId)
  if (!course) return { ok: false, message: t("errors.notFound") }
  if (course.teacherId !== ctx.userId) {
    return { ok: false, message: t("errors.noOwnership") }
  }
  return { ok: true }
}

export async function createElectiveCourseAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("elective")
    const ctx = await requirePermission(Permissions.ELECTIVE_MANAGE)
    const parsed = CreateElectiveCourseSchema.safeParse({
      name: formData.get("name"),
      subjectId: formData.get("subjectId") || undefined,
      teacherId: formData.get("teacherId") || ctx.userId,
      gradeId: formData.get("gradeId") || undefined,
      description: formData.get("description") || undefined,
      capacity: formData.get("capacity") || undefined,
      classroom: formData.get("classroom") || undefined,
      schedule: formData.get("schedule") || undefined,
      startDate: formData.get("startDate") || undefined,
      endDate: formData.get("endDate") || undefined,
      selectionStartAt: formData.get("selectionStartAt") || undefined,
      selectionEndAt: formData.get("selectionEndAt") || undefined,
      selectionMode: formData.get("selectionMode") || undefined,
      credit: formData.get("credit") || undefined,
    })
    if (!parsed.success) {
      return {
        success: false,
        message: t("errors.invalidForm"),
        errors: parsed.error.flatten().fieldErrors,
      }
    }
    const id = await createElectiveCourse(parsed.data, ctx.userId)
    revalidateElectivePaths(id)
    await trackEvent({
      event: "elective.course_created",
      userId: ctx.userId,
      targetId: id,
      targetType: "elective_course",
      properties: { capacity: parsed.data.capacity, selectionMode: parsed.data.selectionMode },
    })
    return { success: true, message: t("messages.created"), data: id }
  } catch (e) {
    const t = await getTranslations("elective")
    const translated = await translateBusinessError(e, t)
    if (translated) return { success: false, message: translated }
    return handleActionError(e)
  }
}

export async function updateElectiveCourseAction(
  id: string,
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("elective")
    const ctx = await requirePermission(Permissions.ELECTIVE_MANAGE)

    const ownership = await assertCourseOwnership(id, ctx)
    if (!ownership.ok) {
      return { success: false, message: ownership.message ?? t("messages.ownershipCheckFailed") }
    }

    const parsed = UpdateElectiveCourseSchema.safeParse({
      name: formData.get("name") || undefined,
      subjectId: formData.get("subjectId") || undefined,
      teacherId: formData.get("teacherId") || undefined,
      gradeId: formData.get("gradeId") || undefined,
      description: formData.get("description") || undefined,
      capacity: formData.get("capacity") || undefined,
      classroom: formData.get("classroom") || undefined,
      schedule: formData.get("schedule") || undefined,
      startDate: formData.get("startDate") || undefined,
      endDate: formData.get("endDate") || undefined,
      selectionStartAt: formData.get("selectionStartAt") || undefined,
      selectionEndAt: formData.get("selectionEndAt") || undefined,
      status: formData.get("status") || undefined,
      selectionMode: formData.get("selectionMode") || undefined,
      credit: formData.get("credit") || undefined,
    })
    if (!parsed.success) {
      return {
        success: false,
        message: t("errors.invalidForm"),
        errors: parsed.error.flatten().fieldErrors,
      }
    }
    await updateElectiveCourse(id, parsed.data)
    revalidateElectivePaths(id)
    await trackEvent({
      event: "elective.course_updated",
      userId: ctx.userId,
      targetId: id,
      targetType: "elective_course",
    })
    return { success: true, message: t("messages.updated"), data: id }
  } catch (e) {
    const t = await getTranslations("elective")
    const translated = await translateBusinessError(e, t)
    if (translated) return { success: false, message: translated }
    return handleActionError(e)
  }
}

export async function deleteElectiveCourseAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("elective")
    const ctx = await requirePermission(Permissions.ELECTIVE_MANAGE)
    const id = requireCourseId(formData)

    const ownership = await assertCourseOwnership(id, ctx)
    if (!ownership.ok) {
      return { success: false, message: ownership.message ?? t("messages.ownershipCheckFailed") }
    }

    await deleteElectiveCourse(id)
    revalidateElectivePaths()
    await trackEvent({
      event: "elective.course_deleted",
      userId: ctx.userId,
      targetId: id,
      targetType: "elective_course",
    })
    return { success: true, message: t("messages.deleted") }
  } catch (e) {
    const t = await getTranslations("elective")
    const translated = await translateBusinessError(e, t)
    if (translated) return { success: false, message: translated }
    return handleActionError(e)
  }
}

export async function openSelectionAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("elective")
    const ctx = await requirePermission(Permissions.ELECTIVE_MANAGE)
    const courseId = requireCourseId(formData)

    const ownership = await assertCourseOwnership(courseId, ctx)
    if (!ownership.ok) {
      return { success: false, message: ownership.message ?? t("messages.ownershipCheckFailed") }
    }

    await openSelection(courseId)
    revalidateElectivePaths(courseId)
    await trackEvent({
      event: "elective.selection_opened",
      userId: ctx.userId,
      targetId: courseId,
      targetType: "elective_course",
    })
    return { success: true, message: t("messages.selectionOpened") }
  } catch (e) {
    const t = await getTranslations("elective")
    const translated = await translateBusinessError(e, t)
    if (translated) return { success: false, message: translated }
    return handleActionError(e)
  }
}

export async function closeSelectionAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("elective")
    const ctx = await requirePermission(Permissions.ELECTIVE_MANAGE)
    const courseId = requireCourseId(formData)

    const ownership = await assertCourseOwnership(courseId, ctx)
    if (!ownership.ok) {
      return { success: false, message: ownership.message ?? t("messages.ownershipCheckFailed") }
    }

    await closeSelection(courseId)
    revalidateElectivePaths(courseId)
    await trackEvent({
      event: "elective.selection_closed",
      userId: ctx.userId,
      targetId: courseId,
      targetType: "elective_course",
    })
    return { success: true, message: t("messages.selectionClosed") }
  } catch (e) {
    const t = await getTranslations("elective")
    const translated = await translateBusinessError(e, t)
    if (translated) return { success: false, message: translated }
    return handleActionError(e)
  }
}

export async function runLotteryAction(
  prevState: ActionState<{ enrolled: number; waitlist: number }> | null,
  formData: FormData
): Promise<ActionState<{ enrolled: number; waitlist: number }>> {
  try {
    const t = await getTranslations("elective")
    const ctx = await requirePermission(Permissions.ELECTIVE_MANAGE)
    const parsed = RunLotterySchema.safeParse({
      courseId: formData.get("courseId"),
    })
    if (!parsed.success) {
      return {
        success: false,
        message: t("errors.invalidForm"),
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    const ownership = await assertCourseOwnership(parsed.data.courseId, ctx)
    if (!ownership.ok) {
      return { success: false, message: ownership.message ?? t("messages.ownershipCheckFailed") }
    }

    const result = await runLottery(parsed.data.courseId)
    revalidateElectivePaths(parsed.data.courseId)
    await trackEvent({
      event: "elective.lottery_completed",
      userId: ctx.userId,
      targetId: parsed.data.courseId,
      targetType: "elective_course",
      properties: { enrolled: result.enrolled, waitlist: result.waitlist },
    })
    return {
      success: true,
      message: t("messages.lotteryCompleted", { enrolled: result.enrolled, waitlist: result.waitlist }),
      data: result,
    }
  } catch (e) {
    const t = await getTranslations("elective")
    const translated = await translateBusinessError(e, t)
    if (translated) return { success: false, message: translated }
    return handleActionError(e)
  }
}

export async function selectCourseAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("elective")
    const ctx = await requirePermission(Permissions.ELECTIVE_SELECT)
    const parsed = SelectCourseSchema.safeParse({
      courseId: formData.get("courseId"),
      priority: formData.get("priority") || undefined,
    })
    if (!parsed.success) {
      return {
        success: false,
        message: t("errors.invalidForm"),
        errors: parsed.error.flatten().fieldErrors,
      }
    }
    const result = await selectCourse(parsed.data.courseId, ctx.userId, parsed.data.priority)
    revalidateElectivePaths(parsed.data.courseId)
    await trackEvent({
      event: "elective.course_selected",
      userId: ctx.userId,
      targetId: parsed.data.courseId,
      targetType: "course_selection",
      properties: { status: result.status, priority: parsed.data.priority },
    })
    // 通过 i18n 翻译选课结果状态（result.status 已是 CourseSelectionStatus 类型）
    const statusKey = COURSE_SELECTION_STATUS_LABEL_KEYS[result.status]
    return { success: true, message: t(statusKey), data: result.status }
  } catch (e) {
    const t = await getTranslations("elective")
    const translated = await translateBusinessError(e, t)
    if (translated) return { success: false, message: translated }
    return handleActionError(e)
  }
}

export async function dropCourseAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const t = await getTranslations("elective")
    const ctx = await requirePermission(Permissions.ELECTIVE_SELECT)
    const parsed = DropCourseSchema.safeParse({
      courseId: formData.get("courseId"),
    })
    if (!parsed.success) {
      return {
        success: false,
        message: t("errors.invalidForm"),
        errors: parsed.error.flatten().fieldErrors,
      }
    }
    await dropCourse(parsed.data.courseId, ctx.userId, parsed.data.dropReason)
    revalidateElectivePaths(parsed.data.courseId)
    await trackEvent({
      event: "elective.course_dropped",
      userId: ctx.userId,
      targetId: parsed.data.courseId,
      targetType: "course_selection",
    })
    return { success: true, message: t("messages.courseDropped") }
  } catch (e) {
    const t = await getTranslations("elective")
    const translated = await translateBusinessError(e, t)
    if (translated) return { success: false, message: translated }
    return handleActionError(e)
  }
}
