import { jsonError } from "../../common.js";
import sendEmail from "../../email.js";
import { sendPushNotification } from "../../gcloud.js";

export async function onRequestDelete(context: RequestContext) {
  const result = await context.env.D1.prepare(
    "SELECT json_extract(user, '*.id') AS uid FROM inactivity_notices WHERE id = ?;",
  )
    .bind(context.params.id)
    .first();

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

  if (
    result.uid !== 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 onRequestPost(context: RequestContext) {
  const { accepted }: { accepted?: boolean } = 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: { [k: string]: any } | null =
    await context.env.D1.prepare(
      "SELECT decisions, departments, user FROM inactivity_notices WHERE id = ?;",
    )
      .bind(context.params.id)
      .first();

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

  const decisions: { [dept: string]: boolean } = JSON.parse(
    requestedNotice.decisions,
  );

  for (const department of userAdminDepartments)
    decisions[department] = accepted;

  const applicableDepartments = JSON.parse(requestedNotice.departments).length;

  await context.env.D1.prepare(
    "UPDATE inactivity_notices SET decisions = ?, user = json_remove(user, '$.email') WHERE id = ?;",
  )
    .bind(JSON.stringify(decisions), context.params.id)
    .run();

  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: FCMTokenResult | null = await context.env.D1.prepare(
      "SELECT token FROM push_notifications WHERE event_id = ? AND event_type = 'inactivity';",
    )
      .bind(context.params.id)
      .first();

    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.env.D1.prepare(
        "DELETE FROM push_notifications WHERE event_id = ? AND event_type = 'inactivity';",
      ).bind(context.params.id);
    } else {
      await sendEmail(
        requestedNotice.user.email,
        context.env.MAILGUN_API_KEY,
        `Inactivity Request ${approved ? "Approved" : "Denied"}`,
        `inactivity_${approved ? "approved" : "denied"}`,
        { username: requestedNotice.user.username },
      );
    }
  }

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