"use server";

import { revalidatePath } from "next/cache";
import { prisma } from "@/lib/prisma";
import { SPECIAL_PERMISSIONS, hashPassword } from "@/lib/auth";
import { logActivity } from "@/lib/activity";
import { DEPARTMENTS, type Operation } from "@/lib/format";
import { actor, failure, removing } from "./guard";

export async function saveUser(formData: FormData) {
  const user = await actor("users", formData.get("id") ? "edit" : "create", formData);
  const id = String(formData.get("id") ?? "");
  const data = {
    firstName: String(formData.get("firstName") ?? "").trim(),
    lastName: String(formData.get("lastName") ?? "").trim(),
    phone: String(formData.get("phone") ?? "").trim(),
    email: String(formData.get("email") ?? "").trim().toLowerCase(),
    roleId: String(formData.get("roleId") ?? ""),
    active: formData.get("active") === "on",
  };
  const password = String(formData.get("password") ?? "");
  if (id) {
    const previous = await prisma.user.findUnique({ where: { id } });
    await prisma.user.update({
      where: { id },
      data: {
        ...data,
        ...(password ? { passwordHash: await hashPassword(password) } : {}),
      },
    });
    await logActivity(user, "users", "edit", `${data.firstName} ${data.lastName}`, id, previous?.email, data.email);
  } else {
    if (!password) throw await failure("Password is required for a new user.");
    const created = await prisma.user.create({
      data: { ...data, passwordHash: await hashPassword(password) },
    });
    await logActivity(user, "users", "create", `${data.firstName} ${data.lastName}`, created.id, undefined, data.email);
  }
  revalidatePath("/users");
}

export async function setUserActive(id: string, active: boolean, formData: FormData) {
  const user = await actor("users", "edit", formData);
  const previous = await prisma.user.findUnique({ where: { id } });
  await prisma.user.update({ where: { id }, data: { active } });
  await logActivity(user, "users", "edit", `${previous?.firstName} ${previous?.lastName}`, id, String(previous?.active), String(active));
  revalidatePath("/users");
}

export async function deleteUser(id: string, formData: FormData) {
  const user = await actor("users", "delete", formData);
  const previous = await prisma.user.findUnique({ where: { id } });
  await removing(`${previous?.firstName} ${previous?.lastName}`, () => prisma.user.delete({ where: { id } }));
  await logActivity(user, "users", "delete", `${previous?.firstName} ${previous?.lastName}`, id, previous?.email);
  revalidatePath("/users");
}

export async function saveRole(formData: FormData) {
  const user = await actor("users", formData.get("id") ? "edit" : "create", formData);
  const id = String(formData.get("id") ?? "");
  const name = String(formData.get("name") ?? "").trim();
  const matrix: Record<string, Operation[]> = {};
  for (const department of DEPARTMENTS) {
    const ops = ["view", "create", "edit", "delete"].filter(
      (op) => formData.get(`${department}:${op}`) === "on",
    ) as Operation[];
    matrix[department] = ops;
  }
  const special = SPECIAL_PERMISSIONS.filter((permission) => formData.get(`special:${permission}`) === "on");
  const permissions = { ...matrix, special };
  if (id) {
    const previous = await prisma.role.findUnique({ where: { id } });
    await prisma.role.update({ where: { id }, data: { name, permissions: JSON.stringify(permissions) } });
    await logActivity(user, "users", "edit", `Role ${name}`, id, previous?.permissions, JSON.stringify(permissions));
  } else {
    const created = await prisma.role.create({ data: { name, permissions: JSON.stringify(permissions) } });
    await logActivity(user, "users", "create", `Role ${name}`, created.id);
  }
  revalidatePath("/users");
}

export async function deleteRole(id: string, formData: FormData) {
  const user = await actor("users", "delete", formData);
  const previous = await prisma.role.findUnique({ where: { id } });
  await removing(previous?.name ?? "This role", () => prisma.role.delete({ where: { id } }));
  await logActivity(user, "users", "delete", `Role ${previous?.name}`, id);
  revalidatePath("/users");
}
