import { FastifyReply, FastifyRequest } from "fastify";
import prisma from "../../utils/prisma";
import { IdParamsSchema } from "../../utils/schema";
import { getPresignedUrl } from "../../utils/minio";
import { AppointmentCommentSchema } from "./schema";

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

export async function getAppointments(
  req: FastifyRequest,
  reply: FastifyReply
) {
  const appointments = await prisma.appointment.findMany({
    orderBy: {
      date: "desc",
    },
    where: {
      active: true,
      activationDate: {
        lte: new Date(),
      },
      date: {
        gte: new Date(),
      },
    },
    select: {
      id: true,
      title: true,
      date: true,
      time: true,
      address: true,
      images: true,
    },
  });

  const newAppointments = await Promise.all(
    appointments.map(async (appointment) => {
      const presignedImages = await Promise.all(
        appointment.images.map(async (image) => await getPresignedUrl(image))
      );
      return {
        id: appointment.id,
        title: appointment.title,
        date: appointment.date,
        time: appointment.time,
        address: appointment.address,
        presignedImages,
      };
    })
  );

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

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

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

  const appointment = await prisma.appointment.findUnique({
    where: {
      id: id,
      active: true,
      activationDate: {
        lte: new Date(),
      },
      date: {
        gte: new Date(),
      },
    },
    include: {
      comments: {
        orderBy: { createdAt: "asc" },
        include: {
          user: {
            select: {
              id: true,
              firstName: true,
              lastName: true,
            },
          },
        },
      },
      likes: true,
      registrations: {
        where: {
          userId: userId,
        },
      },
    },
  });

  if (!appointment) {
    return reply.code(404).send({
      message: "Cet événement n'existe pas",
    });
  }

  const presignedImages = await Promise.all(
    appointment.images.map(async (image) => await getPresignedUrl(image))
  );

  const finalAppointment = {
    ...appointment,
    presignedImages: presignedImages,
  };
  return reply.code(200).send(finalAppointment);
}

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

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

  const appointment = await prisma.appointment.findUnique({
    where: {
      id: id,
    },
  });

  if (!appointment) {
    return reply.code(404).send({
      message: "Cet événement n'existe pas",
    });
  }

  const oldAppointmentLike = await prisma.appointmentLike.findFirst({
    where: {
      appointmentId: appointment.id,
      userId: userId,
    },
  });

  if (oldAppointmentLike) {
    await prisma.appointmentLike.delete({
      where: {
        id: oldAppointmentLike.id,
      },
    });

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

  const appointmentLike = await prisma.appointmentLike.create({
    data: {
      appointmentId: appointment.id,
      userId: userId,
    },
  });

  return reply.code(200).send(appointmentLike);
}
// ------------------------------------------------------------------------------------

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

  const appointment = await prisma.appointment.findUnique({
    where: {
      id: id,
    },
  });

  if (!appointment) {
    return reply.code(404).send({
      message: "Cet événement n'existe pas",
    });
  }

  const appointmentComment = await prisma.appointmentComment.create({
    data: {
      appointmentId: appointment.id,
      userId: userId,
      content: data.content,
    },
    include: {
      user: {
        select: {
          id: true,
          firstName: true,
          lastName: true,
        },
      },
    },
  });

  return reply.code(200).send(appointmentComment);
}
// ------------------------------------------------------------------------------------

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

  const appointment = await prisma.appointment.findUnique({
    where: {
      id: id,
    },
  });

  if (!appointment) {
    return reply.code(404).send({
      message: "Cet événement n'existe pas",
    });
  }

  const oldAppointmentRegistration =
    await prisma.appointmentRegistration.findFirst({
      where: {
        appointmentId: appointment.id,
        userId: userId,
      },
    });

  if (oldAppointmentRegistration) {
    if (!appointment) {
      return reply.code(400).send({
        message: "Vous êtes déjà inscrit à cet événement",
      });
    }
  }
  const appointmentRegistration = await prisma.appointmentRegistration.create({
    data: {
      appointmentId: appointment.id,
      userId: userId,
    },
  });

  return reply.code(200).send(appointmentRegistration);
}
// ------------------------------------------------------------------------------------
