import { APIEvent } from "@solidjs/start/server";
import { eq } from "drizzle-orm";
import db from "~/drizzle";
import { guilds, matches } from "~/drizzle/schema";
import { BasicAuth } from "~/lib/auth";
import { buildMatches } from "~/lib/responseBuilders";
import { ErrorResponse, Res } from "~/lib/responses";
import { zodBigIntId, zodMatch } from "~/lib/zod";
import { APIResponse, RequestBody } from "~/types/backend";

type Path = "/api/{guildId}/matches";

export const GET = async (
  event: APIEvent,
): Promise<APIResponse<Path, "get">> => {
  switch (event.request.headers.get("authorization")) {
    case BasicAuth.unencoded:
    case BasicAuth.encoded:
      break;

    default:
      return ErrorResponse("UNAUTHORIZED");
  }

  let guildId: bigint;
  try {
    guildId = zodBigIntId.parse(event.params.guildId);
  } catch (e) {
    return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
  }

  const guild = await db.query.guilds
    .findFirst({
      where: eq(guilds.id, guildId),
      with: {
        matches: true,
      },
    })
    .execute();

  if (!guild) return ErrorResponse("NOT_FOUND");

  return Res("OK", {
    matches: buildMatches(guild.matches),
    timezone: guild.timezone,
  });
};

export const POST = async (
  event: APIEvent,
): Promise<APIResponse<Path, "post">> => {
  switch (event.request.headers.get("authorization")) {
    case BasicAuth.unencoded:
    case BasicAuth.encoded:
      break;

    default:
      return ErrorResponse("UNAUTHORIZED");
  }

  let guildId: bigint;
  try {
    guildId = zodBigIntId.parse(event.params.guildId);
  } catch (e) {
    return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
  }

  const guild = await db.query.guilds
    .findFirst({
      where: eq(guilds.id, guildId),
      with: {
        matches: true,
      },
    })
    .execute();

  if (!guild) return ErrorResponse("NOT_FOUND");

  const unparsedBody = await new Response(event.request.body).json();

  let body: RequestBody<Path, "post">;
  try {
    body = zodMatch.parse(unparsedBody);
  } catch (e) {
    return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
  }

  if (body.timezone !== guild.timezone)
    return ErrorResponse(
      "BAD_REQUEST",
      "Match's timezone is different from guild's timezone",
    );

  await db.insert(matches).values({
    guildId: guild.id,
    channelId: BigInt(body.match.channelId),
    roleId: BigInt(body.match.roleId),
    createrId: BigInt(body.match.createrId),
    messageId: BigInt(body.match.messageId),
    matchType: body.match.matchType,
    opponentName: body.match.opponentName,
    utc_ts: new Date(body.match.utc_ts),
  });

  return Res("NO_CONTENT", null);
};
