"use server";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { z } from "zod";
import { requireTeacher } from "@/lib/auth/session";
import { prisma } from "@/lib/db/prisma";
import { mkdir, unlink, writeFile } from "node:fs/promises";
import path from "node:path";
import { randomUUID } from "node:crypto";
import { notifyActiveStudents } from "@/lib/notifications";

const text = (f: FormData, k: string) => String(f.get(k) ?? "").trim();
const slugify = (v: string) => v.toLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");

export async function saveMaster(formData: FormData) {
  await requireTeacher(); const kind=text(formData,"kind"), id=text(formData,"id"), name=text(formData,"name");
  if (!z.string().min(2).max(120).safeParse(name).success) return;
  if(kind==="class") await prisma.class.upsert({where:{id:id||"new"},update:{name,gradeLevel:Number(text(formData,"gradeLevel")),academicYear:text(formData,"academicYear")},create:{name,gradeLevel:Number(text(formData,"gradeLevel")),academicYear:text(formData,"academicYear")}});
  if(kind==="subject") await prisma.subject.upsert({where:{id:id||"new"},update:{name,code:text(formData,"code"),description:text(formData,"description")},create:{name,code:text(formData,"code"),description:text(formData,"description")}});
  if(kind==="category") await prisma.category.upsert({where:{id:id||"new"},update:{name,slug:slugify(name),description:text(formData,"description")},create:{name,slug:slugify(name),description:text(formData,"description")}});
  if(kind==="technology") await prisma.technology.upsert({where:{id:id||"new"},update:{name,slug:slugify(name),description:text(formData,"description"),color:text(formData,"color")||null,isActive:true},create:{name,slug:slugify(name),description:text(formData,"description"),color:text(formData,"color")||null,isActive:true}});
  revalidatePath("/");
  revalidatePath(`/dashboard/${kind === "class" ? "kelas" : kind === "subject" ? "mata-pelajaran" : kind === "technology" ? "teknologi" : "kategori"}`);
}

export async function deleteMaster(formData: FormData) {
  await requireTeacher(); const kind=text(formData,"kind"), id=text(formData,"id");
  try { if(kind==="class") await prisma.class.delete({where:{id}}); if(kind==="subject") await prisma.subject.delete({where:{id}}); if(kind==="category") await prisma.category.delete({where:{id}}); if(kind==="technology") await prisma.technology.delete({where:{id}}); } catch { return; }
  revalidatePath("/"); revalidatePath("/dashboard");
}

const materialSchema=z.object({title:z.string().min(3).max(191),description:z.string().max(2000),classId:z.string().min(1),subjectId:z.string().min(1),categoryId:z.string().min(1),semester:z.coerce.number().int().min(1).max(2),status:z.enum(["DRAFT","PUBLISHED"]),visibility:z.enum(["PUBLIC","STUDENT_ONLY"]),content:z.string().min(2)});
export async function saveMaterial(formData: FormData) {
  const session = await requireTeacher();
  const id = text(formData, "id");
  const parsed = materialSchema.safeParse(Object.fromEntries(formData));
  if (!parsed.success) redirect(`/dashboard/materi/${id ? `${id}/edit` : "baru"}?error=invalid`);
  let content: object;
  try { content = JSON.parse(parsed.data.content); } catch { redirect(`/dashboard/materi/${id ? `${id}/edit` : "baru"}?error=content`); }
  const existing = id ? await prisma.material.findUnique({ where: { id }, select: { status: true, slug: true } }) : null;
  const slug = existing?.slug ?? `${slugify(parsed.data.title)}-${Date.now().toString().slice(-5)}`;
  const data = { ...parsed.data, content, slug, description: parsed.data.description || null, publishedAt: parsed.data.status === "PUBLISHED" ? new Date() : null, authorId: session.user.id };
  if (id) await prisma.material.update({ where: { id }, data }); else await prisma.material.create({ data });
  if (parsed.data.status === "PUBLISHED" && existing?.status !== "PUBLISHED") await notifyActiveStudents({ title: "Materi baru tersedia", message: parsed.data.title, type: "MATERIAL", href: `/materi/${slug}` });
  revalidatePath("/materi");
  redirect("/dashboard/materi");
}
export async function deleteMaterial(formData:FormData){await requireTeacher();await prisma.material.delete({where:{id:text(formData,"id")}});revalidatePath("/materi");redirect("/dashboard/materi");}
const allowed=new Map([["application/pdf","pdf"],["application/zip","zip"],["text/plain","txt"],["image/jpeg","jpg"],["image/png","png"],["image/webp","webp"]]);
function validAttachmentSignature(bytes: Uint8Array, type: string) {
  if (type === "application/pdf") return new TextDecoder().decode(bytes.slice(0, 5)) === "%PDF-";
  if (type === "application/zip") return bytes[0] === 0x50 && bytes[1] === 0x4b;
  if (type === "image/jpeg") return bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff;
  if (type === "image/png") return bytes.slice(0, 8).every((byte, index) => byte === [137, 80, 78, 71, 13, 10, 26, 10][index]);
  if (type === "image/webp") return new TextDecoder().decode(bytes.slice(0, 4)) === "RIFF" && new TextDecoder().decode(bytes.slice(8, 12)) === "WEBP";
  return type === "text/plain" && !bytes.slice(0, 1024).includes(0);
}
export async function uploadAttachment(formData: FormData) {
  await requireTeacher();
  const materialId = text(formData, "materialId"), file = formData.get("file");
  if (!(file instanceof File) || file.size === 0 || file.size > 10 * 1024 * 1024) throw new Error("File tidak valid atau melebihi 10 MB");
  const ext = allowed.get(file.type);
  if (!ext || path.extname(file.name).toLowerCase() !== `.${ext}`) throw new Error("Tipe file tidak diizinkan");
  const bytes = new Uint8Array(await file.arrayBuffer());
  if (!validAttachmentSignature(bytes, file.type)) throw new Error("Isi file tidak sesuai dengan tipe yang dipilih");
  const material = await prisma.material.findUnique({ where: { id: materialId }, select: { id: true } });
  if (!material) throw new Error("Materi tidak ditemukan");
  const dir = path.resolve(process.cwd(), "public", "uploads", "materials");
  await mkdir(dir, { recursive: true });
  const filename = `${randomUUID()}.${ext}`;
  await writeFile(path.join(dir, filename), bytes, { flag: "wx" });
  try { await prisma.materialAttachment.create({ data: { materialId, name: path.basename(file.name).slice(0, 191), path: `/uploads/materials/${filename}`, mimeType: file.type, sizeBytes: BigInt(file.size) } }); }
  catch (error) { await unlink(path.join(dir, filename)).catch(() => undefined); throw error; }
  revalidatePath(`/dashboard/materi/${materialId}/edit`);
}
export async function deleteAttachment(formData:FormData){await requireTeacher();const id=text(formData,"id"),a=await prisma.materialAttachment.findUnique({where:{id}});if(!a)return;await prisma.materialAttachment.delete({where:{id}});const base=path.join(process.cwd(),"public","uploads","materials"),target=path.join(process.cwd(),"public",a.path.replace(/^\//,""));if(target.startsWith(base))await unlink(target).catch(()=>undefined);revalidatePath(`/dashboard/materi/${a.materialId}/edit`);}
