import * as ldap from "@/ldap";
import prisma from "@/prisma";
import { getUser } from "@/auth";
import { getDiscordAvatar } from "@/app/oauth/discord/oauth";
import { getGitHubAvatar } from "@/app/oauth/github/oauth";
import { getLogger } from "@/logger";

type RequestBody = {
  username: string;
  displayName: string;
  email: string;
  password: string;
  avatarBase64: string | null;
};

export async function POST(request: Request) {
  const logger = getLogger("/api/register");

  const user = await getUser();
  if (user == null) return new Response(null, { status: 401 });

  if (user.username !== null) {
    if (!(await ldap.checkUserExists(user.username))) {
      logger.warn(
        { username: user.username },
        "user doesn't exist in ldap anymore"
      );

      user.username = null;
      await prisma.user.update({
        where: {
          id: user.id
        },
        data: {
          username: null
        }
      });
    } else {
      logger.info(`user ${user.username} tried to register twice`);
      // user already has an account, don't re-register
      return new Response(null, { status: 403 });
    }
  }

  const { username, displayName, email, password, avatarBase64 } =
    (await request.json()) as RequestBody;

  // runtime type verification when :pleading:
  if (
    username == undefined ||
    typeof username !== "string" ||
    displayName == undefined ||
    typeof displayName !== "string" ||
    email == undefined ||
    typeof email !== "string" ||
    password == undefined ||
    typeof password !== "string"
  ) {
    return new Response(
      JSON.stringify({
        ok: false,
        error: "invalidBody"
      }),
      { status: 400 }
    );
  }

  if (username.length < 1) {
    return new Response(
      JSON.stringify({
        ok: false,
        error: "usernameShort"
      }),
      { status: 400 }
    );
  }

  if (password.length < 12) {
    return new Response(
      JSON.stringify({
        ok: false,
        error: "passwordShort"
      }),
      { status: 400 }
    );
  }

  let avatarBuf: Buffer | null | undefined;

  if (avatarBase64 !== null && typeof avatarBase64 === "string") {
    avatarBuf = Buffer.from(avatarBase64, "base64");
    if (avatarBuf.length > 1_000_000) {
      return new Response(
        JSON.stringify({
          ok: false,
          error: "avatarBig"
        }),
        { status: 400 }
      );
    }
  }

  const users = await ldap.getUsers();
  for (const user of users) {
    if (user.id.toLowerCase() === username.toLowerCase()) {
      return new Response(
        JSON.stringify({
          ok: false,
          error: "usernameTaken"
        }),
        { status: 400 }
      );
    }
  }

  await ldap.createUser(username, displayName, email, avatarBuf ?? undefined);
  await ldap.setPassword(username, password);

  const outputUser = await prisma.user.update({
    where: {
      id: user.id
    },
    data: {
      username
    }
  });

  logger.info(outputUser, "registered user");
  return new Response(
    JSON.stringify({
      ok: true
    }),
    { status: 201 }
  );
}
