import { jsonError, jsonResponse } from "../../common.js";
import sendEmail from "../../email.js";
import { sendPushNotification } from "../../gcloud.js";
import { type JsonArray, type JsonObject } from "@prisma/client/runtime/client";

export async function onRequestDelete(context: RequestContext) {
  const result = await context.data.prisma.inactivityNotice.findUnique({
    select: {
      user: true,
    },
    where: {
      id: context.params.id as string,
    },
  });

  if (!result) return jsonError("No inactivity notice with that ID", 404);

  if (
    (result.user as JsonObject).id !== context.data.current_user.id &&
    !(context.data.current_user.permissions & (1 << 0))
  )
    return jsonError(
      "You do not have permission to delete this inactivity notice",
      403,
    );

  await context.env.D1.prepare("DELETE FROM inactivity_notices WHERE id = ?;")
    .bind(context.params.id)
    .run();

  return new Response(null, {
    status: 204,
  });
}

export async function onRequestGet(context: RequestContext) {
  const { current_user: currentUser } = context.data;

  if (
    ![1 << 0, 1 << 2, 1 << 3, 1 << 9, 1 << 10].find(
      (p) => currentUser.permissions & p,
    )
  )
    return jsonError("Forbidden", 403);

  const result = await context.data.prisma.inactivityNotice.findUnique({
    where: {
      id: context.params.id as string,
    },
  });

  return jsonResponse(JSON.stringify(result));
}

export async function onRequestPost(context: RequestContext) {
  const { accepted }: { accepted?: any } = context.data.body;

  if (typeof accepted !== "boolean")
    return jsonError("'accepted' must be a boolean", 400);

  const adminDepartments: { [k: string]: number } = {
    DM: 1 << 11,
    ET: 1 << 4,
    FM: 1 << 7,
    WM: 1 << 6,
  };

  const userAdminDepartments = Object.keys(adminDepartments).filter(
    (dept) => context.data.current_user.permissions & adminDepartments[dept],
  );

  if (!userAdminDepartments.length)
    return jsonError("You are not a manager of any departments", 403);

  const requestedNotice = await context.data.prisma.inactivityNotice.findUnique(
    {
      select: {
        decisions: true,
        departments: true,
        user: true,
      },
      where: {
        id: context.params.id as string,
      },
    },
  );

  if (!requestedNotice)
    return jsonError("Inactivity notices does not exist", 404);

  const decisions = requestedNotice.decisions as { [k: string]: boolean };

  for (const department of userAdminDepartments) {
    if (!(requestedNotice.departments as JsonArray).includes(department))
      continue;
    decisions[department] = accepted;
  }

  const applicableDepartments = (requestedNotice.departments as JsonArray)
    .length;
  const user = requestedNotice.user as JsonObject;

  delete user.email;

  await context.data.prisma.inactivityNotice.update({
    data: {
      decisions,
      user,
    },
    where: {
      id: context.params.id as string,
    },
  });

  if (Object.values(decisions).length === applicableDepartments) {
    const approved =
      Object.values(decisions).filter((d) => d).length ===
      applicableDepartments;
    const denied =
      Object.values(decisions).filter((d) => !d).length !==
      applicableDepartments;
    const fcmTokenResult =
      await context.data.prisma.pushNotification.findUnique({
        select: {
          token: true,
        },
        where: {
          event_id: context.params.id as string,
          event_type: "inactivity",
        },
      });

    if (fcmTokenResult) {
      let status = "Approved";

      if (denied) status = "Denied";
      else if (!approved) status = "Partially Approved";

      await sendPushNotification(
        context.env,
        `Inactivity Request ${status}`,
        accepted
          ? "Your inactivity request was approved."
          : `Your inactivity request was ${denied ? "denied" : "partially approved"}, please reach out to management if you require more details.`,
        fcmTokenResult.token,
      );

      await context.data.prisma.pushNotification.delete({
        where: {
          event_id: context.params.id as string,
          event_type: "inactivity",
        },
      });
    } else {
      await sendEmail(
        (requestedNotice.user as JsonObject).email as string,
        context.env.MAILGUN_API_KEY,
        `Inactivity Request ${approved ? "Approved" : "Denied"}`,
        `inactivity_${approved ? "approved" : "denied"}`,
        { username: (requestedNotice.user as JsonObject).username as string },
      );
    }
  }

  return new Response(null, {
    status: 204,
  });
}
