import { jsonError, jsonResponse } from "../../../common.js";
import { InactivityNotice } from "../../../../generated/prisma/client.js";
import {
  JsonObject,
  raw,
} from "../../../../generated/prisma/internal/prismaNamespace.js";

export async function onRequestGet(context: RequestContext): Promise<any> {
  const type = context.params.type as string;
  const { prisma } = context.data;
  const { searchParams } = new URL(context.request.url);
  const before = parseInt(searchParams.get("before") || `${Date.now()}`);
  const showClosed = searchParams.get("showClosed") === "true";
  const tables: { [k: string]: string } = {
    appeal: "appeals",
    gma: "game_appeals",
    inactivity: "inactivity_notices",
    report: "reports",
  };
  const permissions: { [k: string]: number[] } = {
    appeal: [1 << 0, 1 << 11],
    gma: [1 << 5],
    inactivity: [1 << 4, 1 << 6, 1 << 7, 1 << 11, 1 << 12],
    report: [1 << 5],
  };
  const { current_user: currentUser } = context.data;

  if (!tables[type]) return jsonError("Invalid filter type", 400);

  if (!permissions[type].find((p) => currentUser.permissions & p))
    return jsonError("You cannot use this filter", 403);

  if (isNaN(before)) return jsonError("Invalid `before` parameter", 400);

  let rows;

  switch (type) {
    case "appeal":
      rows = await prisma.appeal.findMany({
        orderBy: {
          created_at: "desc",
        },
        take: 25,
        where: {
          created_at: {
            lt: new Date(before),
          },
          approved: showClosed ? { not: null } : null,
        },
      });
      rows.map((r) => {
        delete (r.user as JsonObject).email;

        return r;
      });
      break;

    case "gma":
      rows = await prisma.gameAppeal.findMany({
        orderBy: {
          created_at: "desc",
        },
        take: 25,
        where: {
          created_at: {
            lt: new Date(before),
          },
        },
      });
      break;

    case "inactivity":
      rows = await prisma.$queryRaw<
        InactivityNotice[] & { decision_count: number }[]
      >`
      SELECT *, (SELECT COUNT(*) FROM json_each(decisions)) AS decision_count FROM inactivity_notices WHERE created_at < datetime(${before} / 1000, 'unixepoch') AND decision_count ${showClosed ? raw("=") : raw("!=")} json_array_length(departments);`;

      rows.map((r) => {
        // These come back as strings when using $queryRaw
        r.decisions = JSON.parse(r.decisions as string);
        r.departments = JSON.parse(r.departments as string);
        r.user = JSON.parse(r.user as string);

        delete (r.user as JsonObject).email;

        return r;
      });
      break;

    case "report":
      rows = await prisma.report.findMany({
        orderBy: {
          created_at: "desc",
        },
        take: 25,
        where: {
          created_at: {
            lt: new Date(before),
          },
          open: !showClosed,
        },
      });

      rows.map((r) => {
        delete (r.user as JsonObject | null)?.email;

        return r;
      });

      break;

    default:
      return jsonError("Unknown filter error", 500);
  }

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