"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 { formatDateForFile } from "@/shared/lib/utils"

import { assertClassInScope } from "./lib/scope-check"
import {
  ExcelImportGradesSchema,
  type ExcelImportGradesInput,
} from "./schema"
import { batchCreateGradeRecords } from "./data-access"
import {
  generateGradeImportTemplate,
  parseGradeExcelBuffer,
  parseGradeImportData,
  buildBatchInputFromImport,
  type GradeImportResult,
} from "./import-export"
import { notifyGradeEntered } from "./lib/notify"

/**
 * P3-10: grades 模块成绩 Excel 批量导入相关 Server Actions。
 *
 * 文件拆分自 actions.ts，避免主 actions 文件超过 800 行限制。
 */

/**
 * 下载成绩导入模板（返回 base64 编码的 Excel）。
 *
 * 模板包含：
 * - 学生姓名 / 得分 / 备注 三列
 * - 前 3 行班级学生作为示例
 * - 第 2 行填写说明
 */
export async function downloadGradeImportTemplateAction(params: {
  classId: string
}): Promise<ActionState<{ buffer: string; filename: string }>> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_MANAGE)
    const t = await getTranslations("grades")

    if (!params.classId) {
      return { success: false, message: t("action.classIdRequired") }
    }

    const scopeError = assertClassInScope(ctx.dataScope, params.classId)
    if (scopeError) {
      return { success: false, message: t(`action.scopeError.${scopeError}`) }
    }

    const buffer = await generateGradeImportTemplate({ classId: params.classId })
    const filename = t("excelImport.templateFilename", {
      date: formatDateForFile(),
    })

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

/**
 * P3-10: 从 Excel 批量导入成绩。
 *
 * 输入：FormData，包含：
 * - file: Excel 文件（.xlsx / .xls）
 * - classId: 班级 ID
 * - subjectId: 科目 ID
 * - title: 评估标题
 * - examId?: 关联考试 ID
 * - academicYearId?: 学年 ID
 * - fullScore?: 满分（默认 100）
 * - type?: 类型（exam/quiz/homework/other，默认 exam）
 * - semester?: 学期（"1"/"2"，默认 "1"）
 *
 * 处理流程：
 * 1. 权限校验：GRADE_RECORD_CREATE
 * 2. scope 校验：班级在教师所教范围内
 * 3. 文件格式校验（扩展名 + buffer 解析）
 * 4. 行级数据校验（学生姓名匹配 + score 数值校验）
 * 5. 若全部失败 → 返回错误明细
 * 6. 若部分成功 → 调用 batchCreateGradeRecords 入库
 * 7. 通知相关学生（notifyGradeEntered）
 * 8. 触发异常预警检查（notifyScoreAnomalyIfNeeded 在 actions.ts 主流程中）
 */
export async function importGradesFromExcelAction(
  prevState: ActionState<GradeImportResult> | null,
  formData: FormData
): Promise<ActionState<GradeImportResult>> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_MANAGE)
    const t = await getTranslations("grades")

    // 文件校验
    const file = formData.get("file")
    if (!(file instanceof File)) {
      return { success: false, message: t("excelImport.errorNoFile") }
    }

    const lowerName = file.name.toLowerCase()
    if (!lowerName.endsWith(".xlsx") && !lowerName.endsWith(".xls")) {
      return { success: false, message: t("excelImport.errorInvalidFormat") }
    }

    // 参数校验（Zod）
    const parsed = ExcelImportGradesSchema.safeParse({
      classId: formData.get("classId"),
      subjectId: formData.get("subjectId"),
      title: formData.get("title"),
      examId: formData.get("examId") || undefined,
      academicYearId: formData.get("academicYearId") || undefined,
      fullScore: formData.get("fullScore") || undefined,
      type: formData.get("type") || undefined,
      semester: formData.get("semester") || undefined,
      rows: [], // rows 由 Excel 解析填充，schema 仅校验其他字段
    })

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

    // scope 校验
    const scopeError = assertClassInScope(ctx.dataScope, parsed.data.classId)
    if (scopeError) {
      return { success: false, message: t(`action.scopeError.${scopeError}`) }
    }

    // 解析 Excel
    const bytes = Buffer.from(await file.arrayBuffer())
    const excelRows = await parseGradeExcelBuffer(bytes)

    if (excelRows.length === 0) {
      return { success: false, message: t("excelImport.errorEmptyFile") }
    }

    // 行数上限校验（与 BatchCreateGradeRecordSchema.max(500) 一致）
    if (excelRows.length > 500) {
      return {
        success: false,
        message: t("excelImport.errorTooManyRows", { count: excelRows.length }),
      }
    }

    // 学生匹配 + 行级校验
    const validation = await parseGradeImportData(excelRows, {
      classId: parsed.data.classId,
    })

    // 全部失败 → 返回错误明细
    if (validation.valid.length === 0) {
      return {
        success: false,
        message: t("excelImport.errorAllInvalid", {
          count: validation.invalid.length,
        }),
        data: {
          successCount: 0,
          failedCount: validation.invalid.length,
          invalidRows: validation.invalid,
          unmatchedStudents: validation.unmatched,
          createdIds: [],
        },
      }
    }

    // 构造批量录入参数
    const batchInput = buildBatchInputFromImport({
      classId: parsed.data.classId,
      subjectId: parsed.data.subjectId,
      title: parsed.data.title,
      examId: parsed.data.examId,
      academicYearId: parsed.data.academicYearId,
      fullScore: parsed.data.fullScore,
      type: parsed.data.type,
      semester: parsed.data.semester,
      rows: validation.valid,
    })

    // 入库
    const createdIds = await batchCreateGradeRecords(batchInput, ctx.userId)

    // 通知相关学生（失败不阻断主流程）
    try {
      await notifyGradeEntered({
        subjectId: parsed.data.subjectId,
        title: parsed.data.title,
        studentIds: validation.valid.map((r) => r.studentId),
      })
    } catch {
      // 通知失败不影响导入结果
    }

    // 刷新缓存
    revalidatePath("/teacher/grades")
    revalidatePath("/teacher/grades/entry")
    revalidatePath(`/teacher/grades?classId=${parsed.data.classId}`)

    const result: GradeImportResult = {
      successCount: createdIds.length,
      failedCount: validation.invalid.length,
      invalidRows: validation.invalid,
      unmatchedStudents: validation.unmatched,
      createdIds,
    }

    return {
      success: true,
      message: t("excelImport.successMessage", {
        success: result.successCount,
        failed: result.failedCount,
      }),
      data: result,
    }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * P3-10: 获取导入预览（不写入数据库）。
 *
 * 用于上传文件后、确认提交前的预览页面。
 */
export async function previewGradeImportAction(params: {
  file: File
  classId: string
}): Promise<ActionState<GradeImportResult>> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_MANAGE)
    const t = await getTranslations("grades")

    if (!params.file || !(params.file instanceof File)) {
      return { success: false, message: t("excelImport.errorNoFile") }
    }
    if (!params.classId) {
      return { success: false, message: t("action.classIdRequired") }
    }

    const scopeError = assertClassInScope(ctx.dataScope, params.classId)
    if (scopeError) {
      return { success: false, message: t(`action.scopeError.${scopeError}`) }
    }

    const bytes = Buffer.from(await params.file.arrayBuffer())
    const excelRows = await parseGradeExcelBuffer(bytes)

    if (excelRows.length === 0) {
      return { success: false, message: t("excelImport.errorEmptyFile") }
    }

    if (excelRows.length > 500) {
      return {
        success: false,
        message: t("excelImport.errorTooManyRows", { count: excelRows.length }),
      }
    }

    const validation = await parseGradeImportData(excelRows, {
      classId: params.classId,
    })

    return {
      success: true,
      data: {
        successCount: validation.valid.length,
        failedCount: validation.invalid.length,
        invalidRows: validation.invalid,
        unmatchedStudents: validation.unmatched,
        createdIds: [],
      },
    }
  } catch (e) {
    return handleActionError(e)
  }
}

/**
 * ExcelImportGradesInput 类型导出（供其他模块引用）。
 */
export type { ExcelImportGradesInput }
