"use server"

import { revalidatePath } from "next/cache"
import { after } from "next/server"
import { createId } from "@paralleldrive/cuid2"

import type { ActionState } from "@/shared/types/action-state"
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"
import { logAudit } from "@/shared/lib/audit-logger"
import { UpsertAcademicYearSchema, UpsertDepartmentSchema, UpsertGradeSchema, UpsertSchoolSchema, PromoteGradesSchema } from "./schema"
import {
  createAcademicYear,
  createDepartment,
  createGrade,
  createSchool,
  deleteAcademicYear,
  deleteDepartment,
  deleteGrade,
  deleteSchool,
  promoteGrades,
  updateAcademicYear,
  updateDepartment,
  updateGrade,
  updateSchool,
} from "./data-access"

export async function createDepartmentAction(
  prevState: ActionState<string> | undefined,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.SCHOOL_MANAGE)
    const parsed = UpsertDepartmentSchema.safeParse({
      name: formData.get("name"),
      description: formData.get("description"),
    })
    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    await createDepartment({
      id: createId(),
      name: parsed.data.name,
      description: parsed.data.description ?? null,
    })

    after(() =>
      logAudit({
        action: "department.create",
        module: "school",
        targetType: "department",
        detail: { name: parsed.data.name },
      })
    )

    revalidatePath("/admin/school/departments")
    return { success: true, message: "Department created" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to create department" }
  }
}

export async function updateDepartmentAction(
  departmentId: string,
  prevState: ActionState<string> | undefined,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.SCHOOL_MANAGE)
    const parsed = UpsertDepartmentSchema.safeParse({
      name: formData.get("name"),
      description: formData.get("description"),
    })
    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    await updateDepartment(departmentId, {
      name: parsed.data.name,
      description: parsed.data.description ?? null,
    })

    after(() =>
      logAudit({
        action: "department.update",
        module: "school",
        targetId: departmentId,
        targetType: "department",
        detail: { name: parsed.data.name },
      })
    )

    revalidatePath("/admin/school/departments")
    return { success: true, message: "Department updated" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to update department" }
  }
}

export async function deleteDepartmentAction(departmentId: string): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.SCHOOL_MANAGE)
    await deleteDepartment(departmentId)
    after(() =>
      logAudit({
        action: "department.delete",
        module: "school",
        targetId: departmentId,
        targetType: "department",
      })
    )
    revalidatePath("/admin/school/departments")
    return { success: true, message: "Department deleted" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to delete department" }
  }
}

export async function createAcademicYearAction(
  prevState: ActionState<string> | undefined,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.SCHOOL_MANAGE)
    const parsed = UpsertAcademicYearSchema.safeParse({
      name: formData.get("name"),
      startDate: formData.get("startDate"),
      endDate: formData.get("endDate"),
      isActive: formData.get("isActive") ?? "false",
    })
    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    await createAcademicYear({
      id: createId(),
      name: parsed.data.name,
      startDate: new Date(parsed.data.startDate),
      endDate: new Date(parsed.data.endDate),
      isActive: parsed.data.isActive,
    })

    after(() =>
      logAudit({
        action: "academicYear.create",
        module: "school",
        targetType: "academicYear",
        detail: { name: parsed.data.name },
      })
    )

    revalidatePath("/admin/school/academic-year")
    return { success: true, message: "Academic year created" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to create academic year" }
  }
}

export async function updateAcademicYearAction(
  academicYearId: string,
  prevState: ActionState<string> | undefined,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.SCHOOL_MANAGE)
    const parsed = UpsertAcademicYearSchema.safeParse({
      name: formData.get("name"),
      startDate: formData.get("startDate"),
      endDate: formData.get("endDate"),
      isActive: formData.get("isActive") ?? "false",
    })
    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    await updateAcademicYear(academicYearId, {
      name: parsed.data.name,
      startDate: new Date(parsed.data.startDate),
      endDate: new Date(parsed.data.endDate),
      isActive: parsed.data.isActive,
    })

    after(() =>
      logAudit({
        action: "academicYear.update",
        module: "school",
        targetId: academicYearId,
        targetType: "academicYear",
        detail: { name: parsed.data.name },
      })
    )

    revalidatePath("/admin/school/academic-year")
    return { success: true, message: "Academic year updated" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to update academic year" }
  }
}

export async function deleteAcademicYearAction(academicYearId: string): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.SCHOOL_MANAGE)
    await deleteAcademicYear(academicYearId)
    revalidatePath("/admin/school/academic-year")
    return { success: true, message: "Academic year deleted" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to delete academic year" }
  }
}

export async function createSchoolAction(
  prevState: ActionState<string> | undefined,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.SCHOOL_MANAGE)
    const parsed = UpsertSchoolSchema.safeParse({
      name: formData.get("name"),
      code: formData.get("code"),
    })
    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    await createSchool({
      id: createId(),
      name: parsed.data.name,
      code: parsed.data.code?.trim() ? parsed.data.code.trim() : null,
    })

    after(() =>
      logAudit({ action: "school.create", module: "school", targetType: "school", detail: { name: parsed.data.name } })
    )

    revalidatePath("/admin/school/schools")
    return { success: true, message: "School created" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to create school" }
  }
}

export async function updateSchoolAction(
  schoolId: string,
  prevState: ActionState<string> | undefined,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.SCHOOL_MANAGE)
    const parsed = UpsertSchoolSchema.safeParse({
      name: formData.get("name"),
      code: formData.get("code"),
    })
    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    await updateSchool(schoolId, {
      name: parsed.data.name,
      code: parsed.data.code?.trim() ? parsed.data.code.trim() : null,
    })

    after(() =>
      logAudit({
        action: "school.update",
        module: "school",
        targetId: schoolId,
        targetType: "school",
        detail: { name: parsed.data.name },
      })
    )

    revalidatePath("/admin/school/schools")
    return { success: true, message: "School updated" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to update school" }
  }
}

export async function deleteSchoolAction(schoolId: string): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.SCHOOL_MANAGE)
    await deleteSchool(schoolId)

    after(() =>
      logAudit({ action: "school.delete", module: "school", targetId: schoolId, targetType: "school" })
    )

    revalidatePath("/admin/school/schools")
    revalidatePath("/admin/school/grades")
    return { success: true, message: "School deleted" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to delete school" }
  }
}

export async function createGradeAction(
  prevState: ActionState<string> | undefined,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.GRADE_MANAGE)
    const parsed = UpsertGradeSchema.safeParse({
      schoolId: formData.get("schoolId"),
      name: formData.get("name"),
      order: formData.get("order"),
      gradeHeadId: formData.get("gradeHeadId"),
      teachingHeadId: formData.get("teachingHeadId"),
    })
    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    await createGrade({
      id: createId(),
      schoolId: parsed.data.schoolId,
      name: parsed.data.name,
      order: parsed.data.order,
      gradeHeadId: parsed.data.gradeHeadId,
      teachingHeadId: parsed.data.teachingHeadId,
    })

    after(() =>
      logAudit({
        action: "grade.create",
        module: "school",
        targetType: "grade",
        detail: { name: parsed.data.name, schoolId: parsed.data.schoolId },
      })
    )

    revalidatePath("/admin/school/grades")
    return { success: true, message: "Grade created" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to create grade" }
  }
}

export async function updateGradeAction(
  gradeId: string,
  prevState: ActionState<string> | undefined,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.GRADE_MANAGE)
    const parsed = UpsertGradeSchema.safeParse({
      schoolId: formData.get("schoolId"),
      name: formData.get("name"),
      order: formData.get("order"),
      gradeHeadId: formData.get("gradeHeadId"),
      teachingHeadId: formData.get("teachingHeadId"),
    })
    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    await updateGrade(gradeId, {
      schoolId: parsed.data.schoolId,
      name: parsed.data.name,
      order: parsed.data.order,
      gradeHeadId: parsed.data.gradeHeadId,
      teachingHeadId: parsed.data.teachingHeadId,
    })

    after(() =>
      logAudit({
        action: "grade.update",
        module: "school",
        targetId: gradeId,
        targetType: "grade",
        detail: { name: parsed.data.name, schoolId: parsed.data.schoolId },
      })
    )

    revalidatePath("/admin/school/grades")
    return { success: true, message: "Grade updated" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to update grade" }
  }
}

export async function deleteGradeAction(gradeId: string): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.GRADE_MANAGE)
    await deleteGrade(gradeId)
    after(() =>
      logAudit({
        action: "grade.delete",
        module: "school",
        targetId: gradeId,
        targetType: "grade",
      })
    )
    revalidatePath("/admin/school/grades")
    return { success: true, message: "Grade deleted" }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to delete grade" }
  }
}

export async function promoteGradesAction(
  prevState: ActionState<string> | undefined,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    await requirePermission(Permissions.GRADE_MANAGE)
    const parsed = PromoteGradesSchema.safeParse({
      schoolId: formData.get("schoolId"),
    })
    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    const result = await promoteGrades(parsed.data.schoolId)

    after(() =>
      logAudit({
        action: "grade.promote",
        module: "school",
        targetType: "grade",
        targetId: parsed.data.schoolId,
        detail: { promoted: result.promoted },
      })
    )

    revalidatePath("/admin/school/grades")
    return { success: true, message: `Promoted ${result.promoted} grades` }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    if (error instanceof Error) return { success: false, message: error.message }
    return { success: false, message: "Failed to promote grades" }
  }
}
