"use server";

import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { prisma } from "./prisma";
import { requireCurrentUser, userIsAdmin } from "./session";

const allowedRegistrationModes = ["OPEN", "INVITE_ONLY", "DISABLED"];
const allowedVisibility = ["PUBLIC", "FRIENDS", "EXPLICIT", "ROLE_RESTRICTED"];
const allowedProviders = ["YOUTUBE", "TWITCH", "DIRECT"];

async function requireAdmin() {
  const user = await requireCurrentUser();
  if (!userIsAdmin(user)) {
    redirect("/dashboard");
  }
  return user;
}

export async function updateInstanceSettings(formData: FormData) {
  await requireAdmin();
  const instanceName = String(formData.get("instanceName") || "WatchLink").trim().slice(0, 80) || "WatchLink";
  const instanceDescription = String(formData.get("instanceDescription") || "").trim().slice(0, 240);
  const defaultRoomVisibility = normalizeChoice(String(formData.get("defaultRoomVisibility") || "FRIENDS"), allowedVisibility, "FRIENDS");
  const selectedProviders = allowedProviders.filter((provider) => formData.getAll("allowedProviders").includes(provider));
  const maxAvatarUploadMb = Math.min(10, Math.max(1, Number(formData.get("maxAvatarUploadMb") || 2) || 2));

  await writeSettings({
    instanceName,
    instanceDescription,
    defaultRoomVisibility,
    allowedProviders: selectedProviders.length > 0 ? selectedProviders.join(",") : "YOUTUBE,TWITCH,DIRECT",
    maxAvatarUploadMb: String(maxAvatarUploadMb)
  });

  revalidateSettingsPaths();
  redirect("/admin?tab=Instance&saved=1");
}

export async function updateSecuritySettings(formData: FormData) {
  await requireAdmin();
  const registrationMode = normalizeChoice(String(formData.get("registrationMode") || "OPEN"), allowedRegistrationModes, "OPEN");
  await writeSettings({ registrationMode });
  revalidateSettingsPaths();
  redirect("/admin?tab=Security&saved=1");
}

async function writeSettings(values: Record<string, string>) {
  await prisma.$transaction(
    Object.entries(values).map(([key, value]) =>
      prisma.appSetting.upsert({
        where: { key },
        update: { value },
        create: { key, value }
      })
    )
  );
}

function normalizeChoice<T extends string>(value: string, allowed: T[], fallback: T) {
  return allowed.includes(value as T) ? (value as T) : fallback;
}

function revalidateSettingsPaths() {
  revalidatePath("/admin");
  revalidatePath("/dashboard");
  revalidatePath("/rooms");
  revalidatePath("/register");
}
