import { NextResponse } from "next/server"

import { requireAuth, requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"
import { formatDateForFile } from "@/shared/lib/utils"
import { exportUsersToExcel } from "@/modules/users/import-export"
import { exportGradeRecordsToExcel } from "@/modules/grades/export"
import { exportAttendanceRecordsToExcel } from "@/modules/attendance/export"
import { exportElectiveCoursesToExcel, exportCourseSelectionsToExcel } from "@/modules/elective/export"
import {
  exportAuditLogsAction,
  exportDataChangeLogsAction,
  exportLoginLogsAction,
} from "@/modules/audit/actions"

export const dynamic = "force-dynamic"

type ExportType =
  | "grades"
  | "users"
  | "attendance"
  | "electiveCourses"
  | "courseSelections"
  | "audit"
  | "login"
  | "dataChange"

const isExportType = (v: string): v is ExportType =>
  v === "grades" ||
  v === "users" ||
  v === "attendance" ||
  v === "electiveCourses" ||
  v === "courseSelections" ||
  v === "audit" ||
  v === "login" ||
  v === "dataChange"

export async function POST(req: Request) {
  try {
    const ctx = await requireAuth()

    const body = (await req.json()) as {
      type?: string
      params?: Record<string, unknown>
    }

    const type = body.type ?? ""
    if (!isExportType(type)) {
      return NextResponse.json(
        { success: false, message: "Invalid export type" },
        { status: 400 }
      )
    }

    const params = body.params ?? {}
    let buffer: Buffer
    let filename: string

    if (type === "grades") {
      buffer = await exportGradeRecordsToExcel({
        classId: String(params.classId ?? ""),
        subjectId: params.subjectId ? String(params.subjectId) : undefined,
        examId: params.examId ? String(params.examId) : undefined,
        scope: ctx.dataScope,
      })
      filename = `grades_export_${formatDateForFile()}.xlsx`
    } else if (type === "users") {
      buffer = await exportUsersToExcel({
        scope: ctx.dataScope,
        role: params.role ? String(params.role) : undefined,
      })
      filename = `users_export_${formatDateForFile()}.xlsx`
    } else if (type === "attendance") {
      // 考勤导出需要 ATTENDANCE_READ 权限
      try {
        await requirePermission(Permissions.ATTENDANCE_READ)
      } catch (e) {
        if (e instanceof PermissionDeniedError) {
          return NextResponse.json(
            { success: false, message: e.message },
            { status: 403 }
          )
        }
        throw e
      }
      buffer = await exportAttendanceRecordsToExcel({
        scope: ctx.dataScope,
        currentUserId: ctx.userId,
        classId: params.classId ? String(params.classId) : undefined,
        status: params.status ? String(params.status) : undefined,
        date: params.date ? String(params.date) : undefined,
      })
      filename = `attendance_export_${formatDateForFile()}.xlsx`
    } else if (type === "electiveCourses") {
      // 选修课导出需要 ELECTIVE_READ 权限
      try {
        await requirePermission(Permissions.ELECTIVE_READ)
      } catch (e) {
        if (e instanceof PermissionDeniedError) {
          return NextResponse.json(
            { success: false, message: e.message },
            { status: 403 }
          )
        }
        throw e
      }
      buffer = await exportElectiveCoursesToExcel({
        status: params.status ? String(params.status) : undefined,
        teacherId: params.teacherId ? String(params.teacherId) : undefined,
      })
      filename = `elective_courses_export_${formatDateForFile()}.xlsx`
    } else if (type === "courseSelections") {
      // 选课名单导出需要 ELECTIVE_MANAGE 权限
      try {
        await requirePermission(Permissions.ELECTIVE_MANAGE)
      } catch (e) {
        if (e instanceof PermissionDeniedError) {
          return NextResponse.json(
            { success: false, message: e.message },
            { status: 403 }
          )
        }
        throw e
      }
      buffer = await exportCourseSelectionsToExcel({
        courseId: String(params.courseId ?? ""),
      })
      filename = `course_selections_export_${formatDateForFile()}.xlsx`
    } else if (type === "audit" || type === "login" || type === "dataChange") {
      // Audit-related exports require AUDIT_LOG_READ permission
      try {
        await requirePermission(Permissions.AUDIT_LOG_READ)
      } catch (e) {
        if (e instanceof PermissionDeniedError) {
          return NextResponse.json(
            { success: false, message: e.message },
            { status: 403 }
          )
        }
        throw e
      }

      const stringParams: Record<string, string> = {}
      for (const [k, v] of Object.entries(params)) {
        if (typeof v === "string") stringParams[k] = v
      }

      if (type === "audit") {
        const result = await exportAuditLogsAction(stringParams)
        if (!result.success || !result.data) {
          return NextResponse.json(
            { success: false, message: result.message ?? "Export failed" },
            { status: 500 }
          )
        }
        buffer = result.data.buffer
        filename = result.data.filename
      } else if (type === "login") {
        const result = await exportLoginLogsAction(stringParams)
        if (!result.success || !result.data) {
          return NextResponse.json(
            { success: false, message: result.message ?? "Export failed" },
            { status: 500 }
          )
        }
        buffer = result.data.buffer
        filename = result.data.filename
      } else {
        const result = await exportDataChangeLogsAction(stringParams)
        if (!result.success || !result.data) {
          return NextResponse.json(
            { success: false, message: result.message ?? "Export failed" },
            { status: 500 }
          )
        }
        buffer = result.data.buffer
        filename = result.data.filename
      }
    } else {
      return NextResponse.json(
        { success: false, message: "Export type not implemented" },
        { status: 400 }
      )
    }

    return new NextResponse(new Uint8Array(buffer), {
      status: 200,
      headers: {
        "Content-Type":
          "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "Content-Disposition": `attachment; filename="${filename}"`,
        "Content-Length": String(buffer.length),
      },
    })
  } catch (e) {
    const message = e instanceof Error ? e.message : "Export failed"
    const status = message.includes("Permission denied") || message.includes("auth_required")
      ? 401
      : 500
    return NextResponse.json({ success: false, message }, { status })
  }
}
