import { $Enums } from "@prisma/client";
import * as bcrypt from "bcrypt";
import { FastifyReply, FastifyRequest } from "fastify";
import { SALT_ROUNDS } from "../../utils/consts";
import prisma from "../../utils/prisma";
import { IdParamsSchema } from "../../utils/schema";
import {
  EditSubAdminPasswordSchema,
  EditSubAdminSchema,
  SubAdminActiveSchema,
  SubAdminSchema,
} from "./schema";

// ------------------------------------------------------------------------------------

export async function getSubAdmins(req: FastifyRequest, reply: FastifyReply) {
  const subAdmins = await prisma.user.findMany({
    where: { role: $Enums.Role.SubAdmin },
    orderBy: {
      firstName: "desc",
    },
    select: {
      id: true,
      civility: true,
      firstName: true,
      lastName: true,
      email: true,
      phoneNumber: true,

      position: true,
      department: true,
      service: true,

      permissions: true,
      active: true,
      createdAt: true,
    },
  });

  return reply.code(200).send(subAdmins);
}

// ------------------------------------------------------------------------------------

export async function createSubAdmin(
  req: FastifyRequest<{
    Body: SubAdminSchema;
  }>,
  reply: FastifyReply
) {
  const data = req.body;

  const user = await prisma.user.findUnique({
    where: {
      email: data.email.toLowerCase(),
    },
  });

  if (user) {
    return reply.code(400).send({
      message: "Un fonctionnaire avec cette adresse mail existe déjà",
    });
  }

  const position = await prisma.position.findUnique({
    where: {
      id: data.positionId,
    },
  });

  if (!position) {
    return reply.code(400).send({
      message: "La fonction n'existe pas",
    });
  }

  const hash = await bcrypt.hash(data.password, SALT_ROUNDS);
  const subAdmin = await prisma.user.create({
    data: {
      civility: data.civility,
      firstName: data.firstName,
      lastName: data.lastName,
      email: data.email.toLowerCase(),
      password: hash,
      phoneNumber: data.phoneNumber,

      positionId: data.positionId,
      department: data.department,
      service: data.service,

      permissions: data.permissions,
      role: $Enums.Role.SubAdmin,
      bio: "",
    },
    select: {
      id: true,
      civility: true,
      firstName: true,
      lastName: true,
      email: true,
      phoneNumber: true,

      position: true,
      department: true,
      service: true,

      permissions: true,
      active: true,
      createdAt: true,
    },
  });
  return reply.code(200).send(subAdmin);
}
// ------------------------------------------------------------------------------------

export async function editSubAdmin(
  req: FastifyRequest<{
    Params: IdParamsSchema;
    Body: EditSubAdminSchema;
  }>,
  reply: FastifyReply
) {
  const id = req.params.id;
  const data = req.body;

  const subAdmin = await prisma.user.findUnique({
    where: {
      id: id,
      role: $Enums.Role.SubAdmin,
    },
  });

  if (!subAdmin) {
    return reply.code(404).send({
      message: "Ce fonctionnaire n'existe pas",
    });
  }

  const position = await prisma.position.findUnique({
    where: {
      id: data.positionId,
    },
  });

  if (!position) {
    return reply.code(400).send({
      message: "La fonction n'existe pas",
    });
  }

  const nUsers = await prisma.user.count({
    where: {
      id: { not: subAdmin.id },
      email: data.email.toLowerCase(),
    },
  });

  if (nUsers > 0) {
    return reply.code(400).send({
      message: "Un autre fonctionnaire avec cette adresse mail existe déjà",
    });
  }

  const newSubAdmin = await prisma.user.update({
    where: { id: id },
    data: {
      civility: data.civility,
      firstName: data.firstName,
      lastName: data.lastName,
      email: data.email.toLowerCase(),
      phoneNumber: data.phoneNumber,

      positionId: data.positionId,
      department: data.department,
      service: data.service,

      permissions: data.permissions,
    },
    select: {
      id: true,
      civility: true,
      firstName: true,
      lastName: true,
      email: true,
      phoneNumber: true,

      position: true,
      department: true,
      service: true,

      permissions: true,
      active: true,
      createdAt: true,
    },
  });
  return reply.code(200).send(newSubAdmin);
}

// ------------------------------------------------------------------------------------

export async function editSubAdminPassword(
  req: FastifyRequest<{
    Params: IdParamsSchema;
    Body: EditSubAdminPasswordSchema;
  }>,
  reply: FastifyReply
) {
  const id = req.params.id;
  const data = req.body;

  const subAdmin = await prisma.user.findUnique({
    where: {
      id: id,
      role: $Enums.Role.SubAdmin,
    },
  });

  if (!subAdmin) {
    return reply.code(404).send({
      message: "Ce fonctionnaire n'existe pas",
    });
  }

  const hash = await bcrypt.hash(data.password, SALT_ROUNDS);
  await prisma.user.update({
    where: { id: id },
    data: {
      password: hash,
    },
  });
  return reply.code(200).send({});
}

// ------------------------------------------------------------------------------------

export async function editSubAdminActive(
  req: FastifyRequest<{
    Params: IdParamsSchema;
    Body: SubAdminActiveSchema;
  }>,
  reply: FastifyReply
) {
  const id = req.params.id;
  const data = req.body;

  const subAdmin = await prisma.user.findUnique({
    where: {
      id: id,
      role: $Enums.Role.SubAdmin,
    },
  });

  if (!subAdmin) {
    return reply.code(404).send({
      message: "Ce fonctionnaire n'existe pas",
    });
  }

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

  return reply.code(200).send({ active: newSubAdmin.active });
}

// ------------------------------------------------------------------------------------

export async function deleteSubAdmin(
  req: FastifyRequest<{
    Params: IdParamsSchema;
  }>,
  reply: FastifyReply
) {
  const id = req.params.id;

  const subAdmin = await prisma.user.findUnique({
    where: {
      id: id,
      role: $Enums.Role.SubAdmin,
    },
  });

  if (!subAdmin) {
    return reply.code(404).send({
      message: "Ce fonctionnaire n'existe pas",
    });
  }

  await prisma.user.delete({
    where: { id: id },
  });

  return reply.code(200).send({});
}

// ------------------------------------------------------------------------------------
