import { jsonError } from "../../../common.js";
import tokenPrefixes from "../../../../data/token_prefixes.json";

export async function onRequestDelete(context: RequestContext) {
  const authHeader = context.request.headers.get("authorization");

  if (!authHeader) return jsonError("No token provided", 401);

  const payload = JSON.parse(
    atob(authHeader.split(".")[1]).replaceAll("-", "+").replaceAll("_", "/"),
  );

  const tokenHash = await crypto.subtle.digest(
    "SHA-512",
    new TextEncoder().encode(payload.jti),
  );

  await context.env.DATA.delete(
    `auth_${btoa(String.fromCharCode(...new Uint8Array(tokenHash)))
      .replaceAll("+", "-")
      .replaceAll("/", "_")
      .replaceAll("=", "")}`,
  );

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

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

  if (!currentUser) return jsonError("Unauthorized", 401);

  const header = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
  const tokenStart =
    tokenPrefixes[Math.round(Math.random() * (tokenPrefixes.length - 1))] + "_";
  const tokenId =
    tokenStart +
    `${crypto.randomUUID()}${crypto.randomUUID()}${crypto.randomUUID()}${crypto.randomUUID()}`.replaceAll(
      "-",
      "",
    );

  const oauthCredentials = await context.env.DATA.get(
    `oauthcredentials_${currentUser.id}`,
    { type: "json" },
  );

  if (!oauthCredentials) return jsonError("No credentials found for you", 500);

  await context.env.DATA.put(
    `auth_${btoa(
      String.fromCharCode(
        ...new Uint8Array(
          await crypto.subtle.digest(
            "SHA-512",
            new TextEncoder().encode(tokenId),
          ),
        ),
      ),
    )
      .replaceAll("+", "-")
      .replaceAll("/", "_")
      .replaceAll("=", "")}`,
    JSON.stringify(currentUser),
    {
      expirationTtl: 2419200,
    },
  );

  const claimSet = btoa(
    JSON.stringify({
      email: currentUser.email,
      email_verified: true,
      exp: Math.floor(Date.now() / 1000) + 2419200,
      iat: Math.floor(Date.now() / 1000),
      iss: "https://carcrushers.cc/auth/mobile/token",
      jti: tokenId,
      name: currentUser.username,
      permissions: currentUser.permissions,
      picture: currentUser.avatar ?? "https://carcrushers.cc/files/logo192.png",
      sub: currentUser.id,
    }),
  )
    .replaceAll("+", "-")
    .replaceAll("/", "_")
    .replaceAll("=", "");

  const key = await crypto.subtle.importKey(
    "raw",
    // @ts-ignore
    Uint8Array.from(
      atob(
        context.env.JWT_SIGNING_KEY.replaceAll("-", "+").replaceAll("_", "/"),
      ),
      (m) => m.codePointAt(0),
    ),
    { hash: "SHA-256", name: "HMAC" },
    false,
    ["sign"],
  );

  const signature = await crypto.subtle.sign(
    "HMAC",
    key,
    new TextEncoder().encode(`${header}.${claimSet}`),
  );

  const encodedSignature = btoa(
    String.fromCodePoint(...new Uint8Array(signature)),
  )
    .replaceAll("+", "-")
    .replaceAll("/", "_")
    .replaceAll("=", "");

  return new Response(
    `<!DOCTYPE html>
<html>
  <body>
    <p>You were logged in successfully. If this page does not close in a few seconds, please click done.</p>
  </body>
</html>
`,
    {
      headers: {
        "content-type": "text/html",
        location: `com.carcrushers.app://login-callback?token=${header}.${claimSet}.${encodedSignature}`,
      },
      status: 302,
    },
  );
}