"use server"

import { revalidatePath } from "next/cache"
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"
import type { ActionState } from "@/shared/types/action-state"

import {
  CreateGradeRecordSchema,
  BatchCreateGradeRecordSchema,
  UpdateGradeRecordSchema,
  DeleteGradeRecordSchema,
  GetGradeRecordByIdSchema,
  GradeQuerySchema,
  ClassGradeStatsQuerySchema,
  StudentGradeSummaryQuerySchema,
  ClassRankingQuerySchema,
  ExportGradesSchema,
} from "./schema"
import {
  createGradeRecord,
  batchCreateGradeRecords,
  updateGradeRecord,
  deleteGradeRecord,
  getGradeRecords,
  getGradeRecordById,
  getClassGradeStatsWithMeta,
  getStudentGradeSummary,
  getClassRanking,
} from "./data-access"
import {
  exportGradeRecordsToExcel,
  exportClassGradeReportToExcel,
} from "./export"
import { formatDateForFile } from "@/shared/lib/utils"
import type { GradeQueryParams, GradeRecordListItem, GradeStats } from "./types"

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

    const parsed = CreateGradeRecordSchema.safeParse({
      studentId: formData.get("studentId"),
      classId: formData.get("classId"),
      subjectId: formData.get("subjectId"),
      examId: formData.get("examId") || undefined,
      academicYearId: formData.get("academicYearId") || undefined,
      title: formData.get("title"),
      score: formData.get("score"),
      fullScore: formData.get("fullScore") || undefined,
      type: formData.get("type") || undefined,
      semester: formData.get("semester") || undefined,
      remark: formData.get("remark") || undefined,
    })

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

    const id = await createGradeRecord(parsed.data, ctx.userId)
    revalidatePath("/teacher/grades")
    return { success: true, message: "Grade record created", data: id }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

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

    const recordsJson = formData.get("recordsJson")
    if (typeof recordsJson !== "string" || recordsJson.length === 0) {
      return { success: false, message: "Missing records data" }
    }

    const parsed = BatchCreateGradeRecordSchema.safeParse({
      classId: formData.get("classId"),
      subjectId: formData.get("subjectId"),
      examId: formData.get("examId") || undefined,
      academicYearId: formData.get("academicYearId") || undefined,
      title: formData.get("title"),
      fullScore: formData.get("fullScore") || undefined,
      type: formData.get("type") || undefined,
      semester: formData.get("semester") || undefined,
      records: JSON.parse(recordsJson),
    })

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

    const count = await batchCreateGradeRecords(parsed.data, ctx.userId)
    revalidatePath("/teacher/grades")
    return { success: true, message: `Created ${count} grade records`, data: count }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

export async function updateGradeRecordAction(
  id: string,
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.GRADE_RECORD_MANAGE)

    const parsed = UpdateGradeRecordSchema.safeParse({
      title: formData.get("title") || undefined,
      score: formData.get("score") || undefined,
      fullScore: formData.get("fullScore") || undefined,
      type: formData.get("type") || undefined,
      semester: formData.get("semester") || undefined,
      remark: formData.get("remark") || undefined,
      examId: formData.get("examId") || undefined,
    })

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

    await updateGradeRecord(id, parsed.data)
    revalidatePath("/teacher/grades")
    return { success: true, message: "Grade record updated" }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

export async function deleteGradeRecordAction(
  id: string
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.GRADE_RECORD_MANAGE)

    const parsed = DeleteGradeRecordSchema.safeParse({ id })
    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid id",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    await deleteGradeRecord(parsed.data.id)
    revalidatePath("/teacher/grades")
    return { success: true, message: "Grade record deleted" }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

export async function getGradeRecordsAction(
  params: GradeQueryParams
): Promise<ActionState<GradeRecordListItem[]>> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_READ)

    const parsed = GradeQuerySchema.safeParse(params)
    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid query parameters",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    const records = await getGradeRecords({
      ...parsed.data,
      scope: ctx.dataScope,
      currentUserId: ctx.userId,
    })
    return { success: true, data: records }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

export async function getClassGradeStatsAction(
  classId: string,
  subjectId?: string,
  examId?: string
): Promise<ActionState<GradeStats | null>> {
  try {
    await requirePermission(Permissions.GRADE_RECORD_READ)

    const parsed = ClassGradeStatsQuerySchema.safeParse({ classId, subjectId, examId })
    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid query parameters",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    const result = await getClassGradeStatsWithMeta(
      parsed.data.classId,
      parsed.data.subjectId,
      parsed.data.examId
    )
    return { success: true, data: result?.stats ?? null }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

export async function getStudentGradeSummaryAction(
  studentId: string
): Promise<ActionState<Awaited<ReturnType<typeof getStudentGradeSummary>>>> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_READ)

    const parsed = StudentGradeSummaryQuerySchema.safeParse({ studentId })
    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid student id",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    if (ctx.dataScope.type === "class_members" && ctx.userId !== parsed.data.studentId) {
      return { success: false, message: "Can only view your own grades" }
    }
    if (
      ctx.dataScope.type === "children" &&
      !ctx.dataScope.childrenIds.includes(parsed.data.studentId)
    ) {
      return { success: false, message: "Can only view your children's grades" }
    }

    const summary = await getStudentGradeSummary(parsed.data.studentId)
    return { success: true, data: summary }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

export async function getClassRankingAction(
  classId: string,
  subjectId?: string,
  examId?: string
): Promise<ActionState<Awaited<ReturnType<typeof getClassRanking>>>> {
  try {
    await requirePermission(Permissions.GRADE_RECORD_READ)

    const parsed = ClassRankingQuerySchema.safeParse({ classId, subjectId, examId })
    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid query parameters",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    const ranking = await getClassRanking(
      parsed.data.classId,
      parsed.data.subjectId,
      parsed.data.examId
    )
    return { success: true, data: ranking }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

export async function getGradeRecordByIdAction(
  id: string
): Promise<ActionState<Awaited<ReturnType<typeof getGradeRecordById>>>> {
  try {
    await requirePermission(Permissions.GRADE_RECORD_READ)

    const parsed = GetGradeRecordByIdSchema.safeParse({ id })
    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid id",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    const record = await getGradeRecordById(parsed.data.id)
    return { success: true, data: record }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

/**
 * 导出成绩单（返回 base64 编码的 Excel）
 */
export async function exportGradesAction(params: {
  classId: string
  subjectId?: string
  examId?: string
  reportType?: "detail" | "class"
}): Promise<ActionState<{ buffer: string; filename: string }>> {
  try {
    const ctx = await requirePermission(Permissions.GRADE_RECORD_READ)

    const parsed = ExportGradesSchema.safeParse(params)
    if (!parsed.success) {
      return {
        success: false,
        message: "Invalid export parameters",
        errors: parsed.error.flatten().fieldErrors,
      }
    }

    let buffer: Buffer
    let filename: string

    if (parsed.data.reportType === "class") {
      buffer = await exportClassGradeReportToExcel({
        classId: parsed.data.classId,
        scope: ctx.dataScope,
      })
      filename = `班级成绩总表_${formatDateForFile()}.xlsx`
    } else {
      buffer = await exportGradeRecordsToExcel({
        classId: parsed.data.classId,
        subjectId: parsed.data.subjectId,
        examId: parsed.data.examId,
        scope: ctx.dataScope,
      })
      filename = `成绩单_${formatDateForFile()}.xlsx`
    }

    return {
      success: true,
      data: {
        buffer: buffer.toString("base64"),
        filename,
      },
    }
  } catch (e) {
    if (e instanceof PermissionDeniedError) {
      return { success: false, message: e.message }
    }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "导出失败" }
  }
}
