"use server";

import { auth } from "@/auth";
import { db } from "@/lib/db";
import { hasPermission } from "@/lib/permissions";
import { z } from "zod";
import bcrypt from "bcryptjs";
import { revalidatePath } from "next/cache";
import type { Role } from "@prisma/client";

type ActionResult = { ok: true } | { error: string };

const userSchema = z.object({
  employeeId: z.string().min(1, "Employee ID is required"),
  name: z.string().min(1, "Name is required"),
  email: z.string().email("Invalid email"),
  role: z.enum(["TECHNICAL", "MANNING", "ACCOUNTS", "MANAGER", "SUPERUSER", "AUDITOR", "ADMIN"]),
  password: z.string().min(8, "Password must be at least 8 characters").optional(),
});

export async function createUser(formData: FormData): Promise<ActionResult> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_users")) {
    return { error: "Unauthorized" };
  }

  const parsed = userSchema.safeParse({
    employeeId: formData.get("employeeId"),
    name: formData.get("name"),
    email: formData.get("email"),
    role: formData.get("role"),
    password: formData.get("password") || undefined,
  });
  if (!parsed.success) return { error: parsed.error.errors[0]?.message ?? "Validation failed" };

  const data = parsed.data;
  if (!data.password) return { error: "Password is required for new users" };

  const exists = await db.user.findFirst({
    where: { OR: [{ email: data.email }, { employeeId: data.employeeId }] },
  });
  if (exists) return { error: "A user with that email or employee ID already exists" };

  const passwordHash = await bcrypt.hash(data.password, 12);
  await db.user.create({
    data: {
      employeeId: data.employeeId,
      name: data.name,
      email: data.email,
      role: data.role as Role,
      passwordHash,
    },
  });

  revalidatePath("/admin/users");
  return { ok: true };
}

export async function updateUser(formData: FormData): Promise<ActionResult> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_users")) {
    return { error: "Unauthorized" };
  }

  const id = formData.get("id") as string;
  if (!id) return { error: "User ID is required" };

  const parsed = userSchema.safeParse({
    employeeId: formData.get("employeeId"),
    name: formData.get("name"),
    email: formData.get("email"),
    role: formData.get("role"),
    password: formData.get("password") || undefined,
  });
  if (!parsed.success) return { error: parsed.error.errors[0]?.message ?? "Validation failed" };

  const data = parsed.data;
  const conflict = await db.user.findFirst({
    where: {
      AND: [
        { id: { not: id } },
        { OR: [{ email: data.email }, { employeeId: data.employeeId }] },
      ],
    },
  });
  if (conflict) return { error: "Another user already has that email or employee ID" };

  const updateData: Parameters<typeof db.user.update>[0]["data"] = {
    employeeId: data.employeeId,
    name: data.name,
    email: data.email,
    role: data.role as Role,
  };
  if (data.password) {
    updateData.passwordHash = await bcrypt.hash(data.password, 12);
  }

  await db.user.update({ where: { id }, data: updateData });
  revalidatePath("/admin/users");
  return { ok: true };
}

export async function deleteUser(id: string): Promise<ActionResult> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_users")) return { error: "Unauthorized" };
  if (id === session.user.id) return { error: "Cannot delete your own account." };

  const inUse = await db.purchaseOrder.findFirst({ where: { submitterId: id } });
  if (inUse) return { error: "Cannot delete: user has submitted purchase orders. Deactivate them instead." };

  await db.$transaction(async (tx) => {
    await tx.notification.deleteMany({ where: { userId: id } });
    await tx.user.delete({ where: { id } });
  });

  revalidatePath("/admin/users");
  return { ok: true };
}

export async function toggleUserActive(userId: string): Promise<ActionResult> {
  const session = await auth();
  if (!session?.user || !hasPermission(session.user.role, "manage_users")) {
    return { error: "Unauthorized" };
  }
  if (userId === session.user.id) return { error: "You cannot deactivate your own account" };

  const user = await db.user.findUnique({ where: { id: userId }, select: { isActive: true } });
  if (!user) return { error: "User not found" };

  await db.user.update({ where: { id: userId }, data: { isActive: !user.isActive } });
  revalidatePath("/admin/users");
  return { ok: true };
}
