"use server";

import { mkdir, writeFile } from "node:fs/promises";
import path from "node:path";
import { compare, hash } from "bcryptjs";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { prisma } from "./prisma";
import { requireCurrentUser } from "./session";
import { getAppSettings } from "./settings";

const avatarTypes = new Map([
  ["image/png", "png"],
  ["image/jpeg", "jpg"],
  ["image/webp", "webp"],
  ["image/gif", "gif"]
]);

export async function updateProfile(formData: FormData) {
  const user = await requireCurrentUser();
  const displayName = String(formData.get("displayName") || user.username).trim().slice(0, 80) || user.username;
  const avatar = formData.get("avatar");
  const data: { displayName: string; avatarUrl?: string } = { displayName };

  if (avatar instanceof File && avatar.size > 0) {
    const settings = await getAppSettings();
    const extension = avatarTypes.get(avatar.type);
    const maxBytes = settings.maxAvatarUploadMb * 1024 * 1024;

    if (!extension || avatar.size > maxBytes) {
      redirect("/account/settings?error=avatar");
    }

    const uploadsDir = path.join(process.cwd(), "public", "uploads", "avatars");
    await mkdir(uploadsDir, { recursive: true });
    const fileName = `${user.id}-${Date.now()}.${extension}`;
    await writeFile(path.join(uploadsDir, fileName), Buffer.from(await avatar.arrayBuffer()));
    data.avatarUrl = `/uploads/avatars/${fileName}`;
  }

  await prisma.user.update({
    where: { id: user.id },
    data
  });

  revalidatePath("/account/profile");
  revalidatePath("/account/settings");
  revalidatePath("/dashboard");
  redirect("/account/settings?saved=1");
}

export async function changePassword(formData: FormData) {
  const user = await requireCurrentUser();
  const currentPassword = String(formData.get("currentPassword") || "");
  const newPassword = String(formData.get("newPassword") || "");
  const confirmPassword = String(formData.get("confirmPassword") || "");

  if (newPassword.length < 10 || newPassword !== confirmPassword) {
    redirect("/account/settings?error=password");
  }

  const account = await prisma.user.findUnique({ where: { id: user.id }, select: { passwordHash: true } });
  if (!account || !(await compare(currentPassword, account.passwordHash))) {
    redirect("/account/settings?error=password");
  }

  await prisma.user.update({
    where: { id: user.id },
    data: { passwordHash: await hash(newPassword, 12) }
  });

  revalidatePath("/account/settings");
  redirect("/account/settings?saved=password");
}
