// lib/auth-options.ts
import { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { prisma } from "./prisma";
import { normalizeEmail } from "./normalize-email";

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prisma),

  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID ?? "",
      clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? "",
      authorization: {
        params: {
          prompt: "select_account",
        },
      },
    }),
  ],

  pages: {
    signIn: "/login",
    error: "/login/unauthorized", // Error code passed in query string as ?error=
  },

  session: {
    strategy: "jwt",
    maxAge: 30 * 24 * 60 * 60, // 30 days
  },

  cookies: {
    sessionToken: {
      name: `__Secure-next-auth.session-token`,
      options: {
        httpOnly: true,
        sameSite: 'lax',
        path: '/',
        secure: process.env.NODE_ENV === 'production',
      },
    },
  },

  callbacks: {
    /**
     * SIGN-IN GATE
     * This callback MUST NOT mutate users.
     * It only decides: allowed or not.
     */
    async signIn({ user, account }) {
      if (!account || !user?.email) {
        return "/login/unauthorized";
      }

      const normalizedEmail = normalizeEmail(user.email);

      if (!normalizedEmail) {
        return "/login/unauthorized";
      }

      /**
       * 1️⃣ Enforce: one OAuth account → one user
       */
      const existingAccount = await prisma.account.findUnique({
        where: {
          provider_providerAccountId: {
            provider: account.provider,
            providerAccountId: account.providerAccountId,
          },
        },
      });

      if (existingAccount && existingAccount.userId !== (user as any).id) {
        // OAuth account already linked to another user → block
        return "/login/unauthorized";
      }

      /**
       * 2️⃣ Check if user already exists
       */
      const existingUser = await prisma.user.findFirst({
        where: {
          email: {
            equals: normalizedEmail,
            mode: "insensitive",
          },
        },
      });

      /**
       * 3️⃣ Admins / Superadmins are always allowed
       */
      if (
        existingUser &&
        (existingUser.role === "admin" || existingUser.role === "superadmin")
      ) {
        return true;
      }

      /**
       * 4️⃣ Regular users must be explicitly approved
       */
      const allowedStudent = await prisma.allowedStudent.findFirst({
        where: {
          email: {
            equals: normalizedEmail,
            mode: "insensitive",
          },
        },
      });

      if (!allowedStudent || !allowedStudent.active) {
        return "/login/unauthorized";
      }

      /**
       * IMPORTANT:
       * - DO NOT create users here
       * - DO NOT link accounts here
       * PrismaAdapter will create the user on first successful login
       */
      return true;
    },

    /**
     * JWT CALLBACK
     * Token is the source of truth for session data.
     * Role must ALWAYS come from the database.
     */
    async jwt({ token, user }) {
      // On first login
      if (user?.id) {
        const dbUser = await prisma.user.findUnique({
          where: { id: user.id },
          select: {
            id: true,
            role: true,
            email: true,
          },
        });

        if (dbUser) {
          token.id = dbUser.id;
          token.role = dbUser.role ?? "user";

          // Attach student levels if applicable
          let levels = "";
          const normalizedDbEmail = normalizeEmail(dbUser.email);

          if (normalizedDbEmail) {
            const allowedStudent = await prisma.allowedStudent.findFirst({
              where: {
                email: {
                  equals: normalizedDbEmail,
                  mode: "insensitive",
                },
              },
              select: { levels: true },
            });

            levels = allowedStudent?.levels ?? "";
          }

          token.levels = levels;
        }
      }

      // Safety fallback
      token.role = token.role ?? "user";

      return token;
    },

    /**
     * SESSION CALLBACK
     * Only exposes data already trusted in the token.
     */
    async session({ session, token }) {
      if (session.user) {
        (session.user as any).id = token.id ?? null;
        (session.user as any).role = token.role ?? "user";
        (session.user as any).levels = token.levels ?? "";
      }

      return session;
    },
  },
};
