"use server"

import { revalidatePath } from "next/cache"
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 { createNotification } from "@/modules/notifications/data-access"
import { getStudentIdsByClassId } from "@/modules/classes/data-access"
import { getParentIdsByStudentIds } from "@/modules/parent/data-access"

import {
  generateDiagnosticReport,
  generateClassDiagnosticReport,
  generateGradeDiagnosticReport,
  publishDiagnosticReport,
  deleteDiagnosticReport,
  getDiagnosticReportById,
} from "./data-access-reports"
import { getClassStudentsByKnowledgePoint } from "./data-access"
import {
  exportDiagnosticReportToExcel,
  buildDiagnosticReportFilename,
} from "./export"
import {
  GenerateStudentReportSchema,
  GenerateClassReportSchema,
  GenerateGradeReportSchema,
  PublishReportSchema,
  DeleteReportSchema,
} from "./schema"

/** 生成学生个人诊断报告 */
export async function generateStudentReportAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.DIAGNOSTIC_MANAGE)

    const parsed = GenerateStudentReportSchema.safeParse({
      studentId: formData.get("studentId"),
      period: formData.get("period"),
    })
    if (!parsed.success) {
      return { success: false, message: "Missing studentId or period" }
    }

    const { studentId, period } = parsed.data
    const id = await generateDiagnosticReport(studentId, period, ctx.userId)
    revalidatePath("/teacher/diagnostic")
    revalidatePath(`/teacher/diagnostic/student/${studentId}`)
    return { success: true, message: "Diagnostic report generated", data: id }
  } catch (e) {
    return handleActionError(e)
  }
}

/** 生成班级诊断报告 */
export async function generateClassReportAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.DIAGNOSTIC_MANAGE)

    const parsed = GenerateClassReportSchema.safeParse({
      classId: formData.get("classId"),
      period: formData.get("period"),
    })
    if (!parsed.success) {
      return { success: false, message: "Missing classId or period" }
    }

    const { classId, period } = parsed.data
    const id = await generateClassDiagnosticReport(classId, period, ctx.userId)
    revalidatePath("/teacher/diagnostic")
    revalidatePath(`/teacher/diagnostic/class/${classId}`)
    return { success: true, message: "Class diagnostic report generated", data: id }
  } catch (e) {
    return handleActionError(e)
  }
}

/** v4-P2-3: 生成年级诊断报告 */
export async function generateGradeReportAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.DIAGNOSTIC_MANAGE)

    const parsed = GenerateGradeReportSchema.safeParse({
      gradeId: formData.get("gradeId"),
      period: formData.get("period"),
    })
    if (!parsed.success) {
      return { success: false, message: "Missing gradeId or period" }
    }

    const { gradeId, period } = parsed.data
    const id = await generateGradeDiagnosticReport(gradeId, period, ctx.userId)
    revalidatePath("/teacher/diagnostic")
    revalidatePath("/admin/diagnostic")
    return { success: true, message: "Grade diagnostic report generated", data: id }
  } catch (e) {
    return handleActionError(e)
  }
}

/** 发布诊断报告 */
export async function publishReportAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.DIAGNOSTIC_MANAGE)

    const parsed = PublishReportSchema.safeParse({
      id: formData.get("id"),
    })
    if (!parsed.success) {
      return { success: false, message: "Missing report id" }
    }

    await publishDiagnosticReport(parsed.data.id)

    // v3-P1-4 + v4-P1-4 + v4-P1-5：发布报告后发送通知
    // - 个人报告：通知学生本人 + 其家长
    // - 班级报告：通知全班学生 + 全班学生家长
    const report = await getDiagnosticReportById(parsed.data.id)
    if (!report) {
      revalidatePath("/teacher/diagnostic")
      return { success: true, message: "Report published" }
    }

    const title = `诊断报告已发布：${report.period ?? "本期"}`
    const content = report.summary ?? "您有一份新的学情诊断报告，请查看详情。"
    const link = "/student/diagnostic"

    // 收集需要通知的学生 ID 列表
    const studentIdsToNotify: string[] = []
    if (report.studentId) {
      // 个人报告：通知单个学生
      studentIdsToNotify.push(report.studentId)
    } else if (report.classId) {
      // v4-P1-4: 班级报告（有 classId）：通知全班学生
      const classStudentIds = await getStudentIdsByClassId(report.classId)
      studentIdsToNotify.push(...classStudentIds)
    }

    // 通知学生本人
    for (const studentId of studentIdsToNotify) {
      try {
        await createNotification({
          userId: studentId,
          type: "diagnostic",
          title,
          content,
          link,
        })
      } catch {
        // 单条通知失败不阻断整体流程
      }
    }

    // v4-P1-5: 通知所有相关家长
    if (studentIdsToNotify.length > 0) {
      try {
        const parentIds = await getParentIdsByStudentIds(studentIdsToNotify)
        for (const parentId of parentIds) {
          try {
            await createNotification({
              userId: parentId,
              type: "diagnostic",
              title,
              content: report.summary ?? "您的孩子有一份新的学情诊断报告，请查看详情。",
              link: "/parent/diagnostic",
            })
          } catch {
            // 单条通知失败不阻断整体流程
          }
        }
      } catch {
        // 家长查询失败不阻断整体流程
      }
    }

    revalidatePath("/teacher/diagnostic")
    return { success: true, message: "Report published" }
  } catch (e) {
    return handleActionError(e)
  }
}

/** 删除诊断报告 */
export async function deleteReportAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.DIAGNOSTIC_MANAGE)

    const parsed = DeleteReportSchema.safeParse({
      id: formData.get("id"),
    })
    if (!parsed.success) {
      return { success: false, message: "Missing report id" }
    }

    await deleteDiagnosticReport(parsed.data.id)
    revalidatePath("/teacher/diagnostic")
    return { success: true, message: "Report deleted" }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * v3-P2-4: 导出诊断报告为 Excel。
 * 返回 base64 编码的 buffer 和文件名，前端通过 Blob 下载。
 */
export async function exportDiagnosticReportAction(
  reportId: string
): Promise<ActionState<{ buffer: string; filename: string }>> {
  try {
    await requirePermission(Permissions.DIAGNOSTIC_READ)

    if (!reportId || typeof reportId !== "string") {
      return { success: false, message: "Missing report id" }
    }

    const report = await getDiagnosticReportById(reportId)
    if (!report) {
      return { success: false, message: "Report not found" }
    }

    const buffer = await exportDiagnosticReportToExcel({ reportId })
    const filename = await buildDiagnosticReportFilename(report.period)

    return {
      success: true,
      data: {
        buffer: buffer.toString("base64"),
        filename,
      },
    }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * v3-P2-5: 获取班级学生在指定知识点上的掌握度列表。
 * 用于班级诊断页面的"按知识点筛选学生"功能。
 */
export async function getClassStudentsByKnowledgePointAction(params: {
  classId: string
  knowledgePointId: string
  threshold?: number
}): Promise<
  ActionState<
    Array<{
      studentId: string
      studentName: string
      masteryLevel: number
      totalQuestions: number
      correctQuestions: number
      lastAssessedAt: string | null
      needsAttention: boolean
    }>
  >
> {
  try {
    const ctx = await requirePermission(Permissions.DIAGNOSTIC_READ)

    if (!params.classId || !params.knowledgePointId) {
      return { success: false, message: "Missing classId or knowledgePointId" }
    }

    // 教师只能查看所教班级
    if (
      ctx.dataScope.type === "class_taught" &&
      !ctx.dataScope.classIds.includes(params.classId)
    ) {
      return { success: false, message: "You can only access classes you teach" }
    }
    // 学生/家长不可访问
    if (ctx.dataScope.type === "class_members" || ctx.dataScope.type === "children") {
      return { success: false, message: "Access denied" }
    }

    const result = await getClassStudentsByKnowledgePoint(
      params.classId,
      params.knowledgePointId,
      { threshold: params.threshold }
    )
    return { success: true, data: result }
  } catch (e) {
    return handleActionError(e)
  }
}
