"use server";

import { revalidatePath } from "next/cache";
import { prisma } from "@/lib/db";
import { ALL_SCOPES, generateToken, hashToken, type Scope } from "@/lib/api-auth";
import { requireAdmin } from "@/lib/admin-guard";

export type CreateTokenResult =
  | { ok: true; token: string; prefix: string; id: string }
  | { ok: false; error: string };

export async function createApiTokenAction(formData: FormData): Promise<CreateTokenResult> {
  const user = await requireAdmin();

  const name = String(formData.get("name") ?? "").trim();
  if (!name) return { ok: false, error: "Thiếu tên token." };

  const env = (String(formData.get("env") ?? "live") === "test" ? "test" : "live") as
    | "live"
    | "test";
  const scopesRaw = formData.getAll("scopes").map(String);
  const scopes: Scope[] = scopesRaw.filter((s): s is Scope =>
    (ALL_SCOPES as string[]).includes(s),
  );
  if (scopes.length === 0) return { ok: false, error: "Chọn ít nhất 1 scope." };

  const ipAllowlist = String(formData.get("ipAllowlist") ?? "")
    .split(",")
    .map((s) => s.trim())
    .filter(Boolean);

  const expiresInDays = Number(formData.get("expiresInDays") ?? 0);
  const expiresAt =
    expiresInDays > 0
      ? new Date(Date.now() + expiresInDays * 24 * 60 * 60 * 1000)
      : null;

  const { full, prefix } = generateToken(env);
  const hash = await hashToken(full);

  const created = await prisma.apiToken.create({
    data: {
      name,
      prefix,
      hash,
      scopes,
      ipAllowlist,
      expiresAt,
      createdBy: user.id,
    },
  });

  await prisma.auditLog.create({
    data: {
      actorId: user.id,
      actorName: user.name,
      actorEmail: user.email,
      source: "admin",
      action: "token.create",
      target: created.id,
      meta: { name, prefix, scopes, env, expiresInDays },
    },
  });

  revalidatePath("/admin/api-tokens");
  return { ok: true, token: full, prefix, id: created.id };
}

export async function revokeApiTokenAction(id: string): Promise<{ ok: boolean; error?: string }> {
  const user = await requireAdmin();
  const tok = await prisma.apiToken.findUnique({ where: { id } });
  if (!tok) return { ok: false, error: "Không tìm thấy token." };
  if (tok.revoked) return { ok: true };
  await prisma.apiToken.update({
    where: { id },
    data: { revoked: true },
  });
  await prisma.auditLog.create({
    data: {
      actorId: user.id,
      actorName: user.name,
      actorEmail: user.email,
      source: "admin",
      action: "token.revoke",
      target: id,
      meta: { name: tok.name, prefix: tok.prefix },
    },
  });
  revalidatePath("/admin/api-tokens");
  return { ok: true };
}
