import { jsonError, jsonResponse } from "../../common.js";

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

  if (
    !currentUser.email ||
    (await context.env.DATA.get("appeal_disabled")) ||
    (await context.env.D1.prepare(
      "SELECT id FROM appeals WHERE open = 1 AND user = ?;",
    )
      .bind(currentUser.id)
      .first()) ||
    (await context.env.DATA.get(`blockedappeal_${currentUser.id}`))
  )
    return jsonResponse('{"can_appeal":false}');

  return jsonResponse('{"can_appeal":true}');
}

export async function onRequestPost(context: RequestContext) {
  if (await context.env.DATA.get("appeal_disabled"))
    return jsonError("Appeals are disabled", 403);

  const { learned, senderTokenId, whyBanned, whyUnban } = context.data.body;

  if (
    typeof learned !== "string" ||
    typeof whyBanned !== "string" ||
    typeof whyUnban !== "string" ||
    !learned.length ||
    learned.length > 2000 ||
    !whyBanned.length ||
    whyBanned.length > 500 ||
    !whyUnban.length ||
    whyUnban.length > 2000
  )
    return jsonError("One or more fields are missing or invalid", 400);

  const { current_user: currentUser } = context.data;

  if (!currentUser.email) return jsonError("No email for this session", 403);

  const existingBlockedAppeal = await context.env.DATA.get(
    `blockedappeal_${currentUser.id}`,
  );

  if (
    existingBlockedAppeal ||
    (await context.env.D1.prepare(
      "SELECT approved FROM appeals WHERE approved IS NULL AND json_extract(user, '$.id') = ?;",
    )
      .bind(currentUser.id)
      .first())
  )
    return jsonError("Appeal already submitted", 403);

  if (
    await context.env.D1.prepare("SELECT * FROM appeal_bans WHERE user = ?;")
      .bind(currentUser.id)
      .first()
  ) {
    await context.env.DATA.put(`blockedappeal_${currentUser.id}`, "1", {
      metadata: { email: currentUser.email },
    });

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

  const appealId = `${currentUser.id}${Date.now()}${crypto
    .randomUUID()
    .replaceAll("-", "")}`;

  await context.env.D1.prepare(
    "INSERT INTO appeals (ban_reason, created_at, id, learned, reason_for_unban, user) VALUES (?, ?, ?, ?, ?, ?);",
  )
    .bind(
      whyBanned,
      Date.now(),
      appealId,
      learned,
      whyUnban,
      JSON.stringify({
        email: currentUser.email,
        id: currentUser.id,
        username: currentUser.username,
      }),
    )
    .run();

  if (typeof senderTokenId === "string") {
    await context.env.D1.prepare(
      "INSERT INTO push_notifications (created_at, event_id, event_type, token) VALUES (?, ?, 'appeal', ?)",
    )
      .bind(Date.now(), appealId, senderTokenId)
      .run();
  }

  await fetch(context.env.APPEALS_WEBHOOK, {
    body: JSON.stringify({
      embeds: [
        {
          title: "Appeal Submitted",
          color: 3756250,
          description: `View this appeal at https://carcrushers.cc/mod-queue?id=${appealId}&type=appeal`,
          fields: [
            {
              name: "Submitter",
              value: `${currentUser.username} (${currentUser.id})`,
            },
          ],
        },
      ],
    }),
    headers: {
      "content-type": "application/json",
    },
    method: "POST",
  });

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