import { NextRequest } from "next/server";
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
import GitHub from "next-auth/providers/github";
import GitLab from "next-auth/providers/gitlab";
import Cognito from "next-auth/providers/cognito";
import { loadConfig, IAppConfig } from "@digiresilience/metamigo-config";
import { MetamigoAdapter } from "app/_lib/nextauth-adapter";
import { CloudflareAccessProvider } from "app/_lib/cloudflare";

const nextAuthOptions = (config: IAppConfig, req: NextRequest) => {
  const { nextAuth, cfaccess } = config;
  const adapter = MetamigoAdapter(config);
  const providers = [];

  const { audience, domain } = cfaccess;
  const cloudflareAccessEnabled = audience && domain;
  if (cloudflareAccessEnabled)
    providers.push(CloudflareAccessProvider(audience, domain, adapter, req as any));
  else {
    if (nextAuth.google?.id)
      providers.push(
        Google({
          clientId: nextAuth.google.id,
          clientSecret: nextAuth.google.secret,
        })
      );

    if (nextAuth.github?.id)
      providers.push(
        GitHub({
          clientId: nextAuth.github.id,
          clientSecret: nextAuth.github.secret,
        })
      );

    if (nextAuth.gitlab?.id)
      providers.push(
        GitLab({
          clientId: nextAuth.gitlab.id,
          clientSecret: nextAuth.gitlab.secret,
        })
      );

    if (nextAuth.cognito?.id)
      providers.push(
        Cognito({
          clientId: nextAuth.cognito.id,
          clientSecret: nextAuth.cognito.secret,
          // domain: nextAuth.cognito.domain,
        })
      );
  }

  if (providers.length === 0)
    throw new Error(
      "No next-auth providers configured. See Metamigo configuration docs."
    );

  return {
    secret: nextAuth.secret,
    session: {
      strategy: "database",
      maxAge: 8 * 60 * 60, // 8 hours
    },
    jwt: {
      secret: nextAuth.secret,
    },
    providers,
    adapter,
    callbacks: {
      async session({ session, user }: any) {
        session.user.id = user.id;
        session.user.userRole = user.userRole;
        return session;
      },
    },
  };
};

const handler = async (req: NextRequest, context: any) => {
  const config = await loadConfig();
  const authOptions = nextAuthOptions(config, req);
  // @ts-expect-error: non-existent property
  return NextAuth(req, context, authOptions);
};

export { handler as GET, handler as POST };
