"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 {
  createAdminClass,
  deleteAdminClass,
  getClassGradeId,
  setClassSubjectTeachers,
  updateAdminClass,
} from "./data-access"
import { isGradeManager } from "@/modules/school/data-access"
import {
  CreateGradeClassSchema,
  UpdateGradeClassSchema,
  DeleteGradeClassSchema,
} from "./schema"
import { parseSubjectTeachers } from "./actions-shared"

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

    const parsed = CreateGradeClassSchema.safeParse({
      name: formData.get("name"),
      gradeId: formData.get("gradeId"),
      teacherId: formData.get("teacherId"),
      schoolName: formData.get("schoolName"),
      schoolId: formData.get("schoolId"),
      grade: formData.get("grade"),
      homeroom: formData.get("homeroom"),
      room: formData.get("room"),
    })
    if (!parsed.success) {
      return { success: false, message: "Class name, grade and teacher are required" }
    }

    const { name, gradeId, teacherId, schoolName, schoolId, grade, homeroom, room } = parsed.data

    // Verify access
    const isManager = await isGradeManager(gradeId, ctx.userId)
    if (!isManager) {
      return { success: false, message: "You do not have permission to create classes for this grade" }
    }

    try {
      const id = await createAdminClass({
        schoolName: schoolName ?? null,
        schoolId: schoolId ?? null,
        name,
        grade: grade ?? "", // Should be passed from UI based on selected grade
        gradeId,
        teacherId,
        homeroom: homeroom ?? null,
        room: room ?? null,
      })
      revalidatePath("/management/grade/classes")
      return { success: true, message: "Class created successfully", data: id }
    } catch (error) {
      return { success: false, message: error instanceof Error ? error.message : "Failed to create class" }
    }
  } catch (e) {
    if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
    throw e
  }
}

export async function updateGradeClassAction(
  classId: string,
  prevState: ActionState | undefined,
  formData: FormData
): Promise<ActionState> {
  try {
    const ctx = await requirePermission(Permissions.CLASS_UPDATE)

    const parsed = UpdateGradeClassSchema.safeParse({
      classId,
      schoolName: formData.get("schoolName"),
      schoolId: formData.get("schoolId"),
      name: formData.get("name"),
      grade: formData.get("grade"),
      gradeId: formData.get("gradeId"),
      teacherId: formData.get("teacherId"),
      homeroom: formData.get("homeroom"),
      room: formData.get("room"),
    })
    if (!parsed.success) {
      return { success: false, message: "Missing class id" }
    }

    const { classId: validatedClassId, schoolName, schoolId, name, grade, gradeId, teacherId, homeroom, room } = parsed.data
    const subjectTeachers = parseSubjectTeachers(formData.get("subjectTeachers") as string | null)

    // Verify access: Check if the class belongs to a managed grade
    const classGradeId = await getClassGradeId(validatedClassId)
    if (!classGradeId) {
      return { success: false, message: "Class not found or not linked to a grade" }
    }

    const isManager = await isGradeManager(classGradeId, ctx.userId)
    if (!isManager) {
      return { success: false, message: "You do not have permission to update this class" }
    }

    // If changing gradeId, verify target grade too
    if (typeof gradeId === "string" && gradeId !== classGradeId) {
      const isTargetManager = await isGradeManager(gradeId, ctx.userId)
      if (!isTargetManager) {
        return { success: false, message: "You do not have permission to move class to this grade" }
      }
    }

    try {
      await updateAdminClass(validatedClassId, {
        schoolName: schoolName ?? undefined,
        schoolId: schoolId ?? undefined,
        name: name ?? undefined,
        grade: grade ?? undefined,
        gradeId: gradeId ?? undefined,
        teacherId: teacherId ?? undefined,
        homeroom: homeroom ?? undefined,
        room: room ?? undefined,
      })

      if (subjectTeachers) {
        await setClassSubjectTeachers({
          classId: validatedClassId,
          assignments: subjectTeachers,
        })
      }

      revalidatePath("/management/grade/classes")
      return { success: true, message: "Class updated successfully" }
    } catch (error) {
      return { success: false, message: error instanceof Error ? error.message : "Failed to update class" }
    }
  } catch (e) {
    if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
    throw e
  }
}

export async function deleteGradeClassAction(classId: string): Promise<ActionState> {
  try {
    const ctx = await requirePermission(Permissions.CLASS_DELETE)

    const parsed = DeleteGradeClassSchema.safeParse({ classId })
    if (!parsed.success) {
      return { success: false, message: "Missing class id" }
    }

    const { classId: validatedClassId } = parsed.data

    // Verify access
    const classGradeId = await getClassGradeId(validatedClassId)
    if (!classGradeId) {
      return { success: false, message: "Class not found or not linked to a grade" }
    }

    const isManager = await isGradeManager(classGradeId, ctx.userId)
    if (!isManager) {
      return { success: false, message: "You do not have permission to delete this class" }
    }

    try {
      await deleteAdminClass(validatedClassId)
      revalidatePath("/management/grade/classes")
      return { success: true, message: "Class deleted successfully" }
    } catch (error) {
      return { success: false, message: error instanceof Error ? error.message : "Failed to delete class" }
    }
  } catch (e) {
    if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
    throw e
  }
}
