"use server";

/**
 * Bulk user actions. Single-user actions still live inline in users/page.tsx;
 * bulk actions get their own file because they're called from the client
 * component <BulkUserActions> via form action.
 */
import { revalidatePath } from "next/cache";
import { headers } from "next/headers";
import { prisma } from "@/lib/db";
import { requireAdmin, audit } from "@/lib/admin-guard";

type BulkResult = {
  ok: boolean;
  changed: number;
  skipped: number;
  message?: string;
};

const ALLOWED_ROLES = new Set(["USER", "ADMIN"]);
const ALLOWED_PLANS = new Set(["FREE", "PREMIUM"]);

function parseUserIds(formData: FormData): string[] {
  const raw = formData.getAll("userIds");
  return raw.map(String).filter((s) => s.length > 0);
}

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

  const role = String(formData.get("role") ?? "");
  if (!ALLOWED_ROLES.has(role)) {
    return { ok: false, changed: 0, skipped: 0, message: "Role không hợp lệ" };
  }

  const ids = parseUserIds(formData);
  if (ids.length === 0) {
    return { ok: false, changed: 0, skipped: 0, message: "Chưa chọn user" };
  }

  // Don't allow demoting yourself in bulk (would lock out admin).
  const targets = ids.filter((id) => !(id === admin.userId && role !== "ADMIN"));
  const skipped = ids.length - targets.length;

  if (targets.length === 0) {
    return {
      ok: false,
      changed: 0,
      skipped,
      message: "Không thể tự hạ quyền chính mình",
    };
  }

  const result = await prisma.user.updateMany({
    where: { id: { in: targets } },
    data: { role },
  });

  await audit({
    actorId: admin.userId,
    actorName: admin.name,
    action: "user.bulk_role_change",
    target: `${targets.length} users`,
    metadata: { ids: targets, to: role, skipped },
    ipAddress: ip ?? undefined,
  });

  revalidatePath("/admin/users");
  return { ok: true, changed: result.count, skipped };
}

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

  const plan = String(formData.get("plan") ?? "");
  if (!ALLOWED_PLANS.has(plan)) {
    return { ok: false, changed: 0, skipped: 0, message: "Plan không hợp lệ" };
  }

  const ids = parseUserIds(formData);
  if (ids.length === 0) {
    return { ok: false, changed: 0, skipped: 0, message: "Chưa chọn user" };
  }

  const result = await prisma.user.updateMany({
    where: { id: { in: ids } },
    data: { plan },
  });

  await audit({
    actorId: admin.userId,
    actorName: admin.name,
    action: "user.bulk_plan_change",
    target: `${ids.length} users`,
    metadata: { ids, to: plan },
    ipAddress: ip ?? undefined,
  });

  revalidatePath("/admin/users");
  return { ok: true, changed: result.count, skipped: 0 };
}

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

  const ids = parseUserIds(formData);
  if (ids.length === 0) {
    return { ok: false, changed: 0, skipped: 0, message: "Chưa chọn user" };
  }

  // Never delete yourself.
  const targets = ids.filter((id) => id !== admin.userId);
  const skipped = ids.length - targets.length;

  if (targets.length === 0) {
    return {
      ok: false,
      changed: 0,
      skipped,
      message: "Không thể tự xóa chính mình",
    };
  }

  // Confirm token: client must echo the count to prevent accidental fire.
  const confirm = String(formData.get("confirm") ?? "");
  if (confirm !== String(targets.length)) {
    return {
      ok: false,
      changed: 0,
      skipped,
      message: `Chưa xác nhận. Gõ "${targets.length}" vào ô xác nhận.`,
    };
  }

  // Snapshot for audit before delete.
  const snap = await prisma.user.findMany({
    where: { id: { in: targets } },
    select: { id: true, email: true, role: true, plan: true },
  });

  const result = await prisma.user.deleteMany({ where: { id: { in: targets } } });

  await audit({
    actorId: admin.userId,
    actorName: admin.name,
    action: "user.bulk_delete",
    target: `${targets.length} users`,
    metadata: { snapshot: snap, skipped },
    ipAddress: ip ?? undefined,
  });

  revalidatePath("/admin/users");
  return { ok: true, changed: result.count, skipped };
}
