import { AppTable, db } from "@/lib/mastoauth/kysely";
import { MastoAuth } from "@/lib/mastoauth/mastoauth";
import { cookies } from "next/headers";
import { NextRequest } from "next/server";
import crypto from "node:crypto";

export async function GET(request: NextRequest) {
  const cookieStore = cookies();
  const instance = request.nextUrl.searchParams.get("instance");
  if (instance == null) return new Response('', {
    status: 400
  });
  let useMiAuth = false;
  const mauth = new MastoAuth(instance);

  // Check if instance is fediblocked

  const fnListRequest = await fetch("https://seirdy.one/pb/FediNuke.txt");
  
  const fnList = await fnListRequest.text();

  if (fnList == null) return new Response('', {
    status: 500
  });

  const ssListRequest = await fetch("https://seirdy.one/pb/spammy-subdomains.txt");
  
  const ssList = await ssListRequest.text();

  if (ssList == null) return new Response('', {
    status: 500
  });

  // Split lists

  const JSONFnList = fnList.split("\n");
  const JSONSsList = ssList.split("\n");

  if (JSONSsList.includes(instance)) return new Response('https://seirdy.one/pb/spammy-subdomains.txt', {
    status: 403
  });

  if (JSONFnList.includes(instance)) return new Response('https://seirdy.one/pb/FediNuke.txt', {
    status: 403
  });

  // Check if instance app exists
  // For github.com, it should
  let existingInstanceApp = await db
      .selectFrom('apps')
      .where('apps.instance_domain', '=', instance)
      .selectAll()
      .executeTakeFirst();

  console.log(instance);

  if (existingInstanceApp == null) {
    // Create new app
    const temp_iapp = await mauth.newApplication();

    // Misskey.
    if (temp_iapp != null)
      existingInstanceApp = {
        instance_domain: instance,
        client_id: temp_iapp.client_id,
        client_secret: temp_iapp.client_secret,
        redirect_uri: temp_iapp.redirect_uri
      } as AppTable;
    else {
      useMiAuth = true;
      existingInstanceApp = {
        instance_domain: instance,
        client_id: "https://abtmtr.link/jams/",
        client_secret: "MISSKEY",
        redirect_uri: "https://abtmtr.link/jams/oauth/code"
      } as AppTable;
    }

    try {
      await db.insertInto('apps')
        .values(existingInstanceApp)
        .returningAll()
        .executeTakeFirstOrThrow();
    } catch (err) {
      return new Response('', {
        status: 500
      });
    }
  }

  const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~";
  const codeVerifier = new Array(128)
    .fill(0)
    .map(() => chars[Math.floor(chars.length * Math.random())])
    .join("");
  console.log('code_verifier', codeVerifier);

  const codeChallenge = crypto
    .createHash("sha256")
    .update(codeVerifier, "ascii")
    .digest("base64url");
  console.log('code_challenge', codeChallenge);

  const state = crypto.randomUUID();
  console.log('state', state);

  cookieStore.set("instance", instance, {
    expires: Date.now() + 604800000
  });
  if (instance == "discord.com")
    return Response.redirect(`https://${instance}/oauth2/authorize?response_type=code&client_id=${existingInstanceApp.client_id}&redirect_uri=${existingInstanceApp.redirect_uri}&scope=identify&state=${state}&integration_type=1`)
  if (instance == "github.com")
    return Response.redirect(`https://${instance}/login/oauth/authorize?client_id=${existingInstanceApp.client_id}&redirect_uri=${existingInstanceApp.redirect_uri}&scope=&state=${state}`)
  if (useMiAuth)
    return Response.redirect(`https://${instance}/oauth/authorize?response_type=code&client_id=${existingInstanceApp.client_id}&redirect_uri=${existingInstanceApp.redirect_uri}&state=${state}&code_challenge=${codeChallenge}&code_challenge_method=S256&scope=read`);
  return Response.redirect(`https://${instance}/oauth/authorize?response_type=code&client_id=${existingInstanceApp.client_id}&redirect_uri=${existingInstanceApp.redirect_uri}&scope=read`);
}