import { FastifyJWT } from "@fastify/jwt";
import { $Enums } from "@prisma/client";
import { FastifyReply, FastifyRequest } from "fastify";
import prisma from "../utils/prisma";

export const auth = async (
  req: FastifyRequest,
  reply: FastifyReply,
  publicAcess: boolean | undefined
) => {
  const bearerToken = req.headers.authorization;
  if (!bearerToken) {
    return reply.status(401).send({ message: "Authentication required" });
  }
  const token = bearerToken.split(" ")[1];
  const decoded = req.jwt.verify<FastifyJWT["user"]>(token);

  const user = await prisma.user.findUnique({
    where: {
      id: decoded.id,
      active: true,
    },
    select: { id: true, role: true, active: true, member: true },
  });

  if (!user || !user.active) {
    return reply.status(401).send({
      message: "Aucun compte actif trouvé avec ces informations",
    });
  }

  if (user.role === $Enums.Role.User && !publicAcess && !user.member) {
    return reply.status(400).send({
      message: "Vous n'êtes pas un adhérant",
    });
  }

  req.user = decoded;
};

export const adminAuth = async (
  req: FastifyRequest,
  reply: FastifyReply,
  permission: $Enums.Permission | null | undefined
) => {
  const bearerToken = req.headers.authorization;
  if (!bearerToken) {
    return reply.status(401).send({ message: "Authentication required" });
  }
  const token = bearerToken.split(" ")[1];
  const decoded = req.jwt.verify<FastifyJWT["user"]>(token);

  if (decoded.role === $Enums.Role.User) {
    return reply.status(401).send({
      message: "Vous n'êtes pas admin ou fonctionnaire",
    });
  }

  // TODO: Find a better way istead of abusing the db

  const user = await prisma.user.findUnique({
    where: {
      id: decoded.id,
      role: { in: [$Enums.Role.Admin, $Enums.Role.SubAdmin] },
      active: true,
    },
    select: { id: true, role: true, permissions: true, active: true },
  });

  if (!user || !user.active) {
    return reply.status(401).send({
      message: "Aucun compte actif trouvé avec ces informations",
    });
  }

  if (
    permission !== undefined && // means everyone have access
    user.role === $Enums.Role.SubAdmin &&
    req.method !== "GET" &&
    permission !== "Settings" &&
    (permission === null ||
      (permission !== null && !user.permissions.includes(permission)))
  ) {
    return reply.status(400).send({
      message:
        "Vous n'avez pas les permissions nécessaires pour effectuer cette action",
    });
  }

  req.user = decoded;
};
