/**
 * Server actions for /admin pages — keep them in one file to avoid
 * inlining "use server" everywhere and to keep a clear audit trail.
 */
"use server";

import { revalidatePath } from "next/cache";
import { headers } from "next/headers";
import { requireAdmin, audit } from "@/lib/admin-guard";
import { setSetting, getSetting, SETTINGS } from "@/lib/settings";

const ALL_KEYS = new Set(SETTINGS.map((s) => s.key));

export async function updateSettingsAction(category: string, formData: FormData) {
  const admin = await requireAdmin();
  const ip = (await headers()).get("x-forwarded-for")?.split(",")[0]?.trim() ?? null;

  const changes: Record<string, { from: string; to: string }> = {};

  for (const [key, raw] of formData.entries()) {
    if (!ALL_KEYS.has(key)) continue;
    const def = SETTINGS.find((s) => s.key === key)!;
    if (def.category !== category) continue;

    const value = typeof raw === "string" ? raw.trim() : "";

    // Secret fields use a special "•••• kept" sentinel from the client UI to
    // mean "leave the existing value alone". Don't clobber it.
    if (def.secret && value.startsWith("••••")) continue;

    const before = await getSetting(key);
    if (before === value) continue;

    await setSetting(key, value, admin.userId);
    changes[key] = {
      from: def.secret ? "••••" : before,
      to: def.secret && value !== "" ? "••••" : value,
    };
  }

  if (Object.keys(changes).length > 0) {
    await audit({
      actorId: admin.userId,
      actorName: admin.name,
      action: "setting.update",
      target: category,
      metadata: { changes },
      ipAddress: ip ?? undefined,
    });
  }

  revalidatePath(`/admin/${category === "ai" ? "ai" : "site"}`);
  revalidatePath("/admin");
  return { ok: true, changedCount: Object.keys(changes).length };
}
