import prisma from "@/prisma";
import { cookies } from "next/dist/client/components/headers";
import { v4 } from "uuid";
import * as ldap from "./ldap";
import { getLogger } from "./logger";

const logger = getLogger("auth.ts");

export async function getUser() {
  const cookieStore = cookies();
  const cookieTicket = cookieStore.get("ticket");
  if (cookieTicket == null) return null;

  const ticket = await prisma.authTicket.findFirst({
    where: {
      ticket: cookieTicket?.value
    }
  });
  if (ticket == null) return null;

  const user = await prisma.user.findFirst({
    where: {
      id: ticket.userId
    }
  });

  if (
    user !== null &&
    user.username !== null &&
    !(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
      }
    });
  }

  return user;
}

export async function createAuthTicket(username: string) {
  let user = await prisma.user.findFirst({
    where: {
      username: username
    }
  });

  // It's possible we haven't made a user yet (already existing accounts)
  if (user === null) {
    user = await prisma.user.create({
      data: {
        username: username
      }
    });
  }

  const authTicket = await prisma.authTicket.upsert({
    where: {
      userId: user!.id
    },
    create: {
      userId: user!.id,
      ticket: v4(),
      expiresAt: new Date(Date.now() + 86400000)
    },
    update: {
      ticket: v4(),
      expiresAt: new Date(Date.now() + 86400000)
    }
  });

  await prisma.user.update({
    where: {
      id: user!.id
    },
    data: {
      authTicket: {
        connect: {
          id: authTicket.id
        }
      }
    }
  });

  return authTicket.ticket;
}

export enum AuthState {
  LoggedOut,
  Registering,
  LoggedIn
}

export async function getAuthState() {
  const user = await getUser();
  if (user === null) return AuthState.LoggedOut;

  const info = ldap.getUserInfo(user);
  if (info === null) return AuthState.Registering;

  return AuthState.LoggedIn;
}
