import NextAuth from "next-auth";
import Credentials from "next-auth/providers/credentials";
import Google from "next-auth/providers/google";
import bcryptjs from "bcryptjs";
import { eq } from "drizzle-orm";
import { db } from "@/lib/db";
import { users } from "@/lib/db/schema";

export const { handlers, auth, signIn, signOut } = NextAuth({
  secret: process.env.AUTH_SECRET,
  session: {
    strategy: "jwt",
    maxAge: 30 * 24 * 60 * 60, // 30 days
  },
  providers: [
    Credentials({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        const email = credentials?.email as string | undefined;
        const password = credentials?.password as string | undefined;

        if (!email || !password) {
          return null;
        }

        const [user] = await db
          .select()
          .from(users)
          .where(eq(users.email, email))
          .limit(1);

        if (!user || !user.password_hash) {
          return null;
        }

        const passwordValid = await bcryptjs.compare(password, user.password_hash);
        if (!passwordValid) {
          return null;
        }

        return {
          id: user.id,
          email: user.email,
          name: user.name,
          image: user.image,
        };
      },
    }),
    Google({
      clientId: process.env.AUTH_GOOGLE_ID,
      clientSecret: process.env.AUTH_GOOGLE_SECRET,
    }),
  ],
  callbacks: {
    async signIn({ user, account, profile }) {
      // Only handle Google OAuth sign-ins here; credentials are handled in authorize()
      if (account?.provider === "google") {
        const email = profile?.email ?? user.email;
        if (!email) {
          return false;
        }

        const [existingUser] = await db
          .select()
          .from(users)
          .where(eq(users.email, email))
          .limit(1);

        if (!existingUser) {
          // First Google sign-in: create a new user record
          await db.insert(users).values({
            email,
            name: profile?.name ?? user.name ?? null,
            image: profile?.picture ?? (user.image ?? null),
            provider: "google",
            provider_account_id: account.providerAccountId,
            password_hash: null,
          });
        }
        // Returning Google sign-in: existing user found, allow sign-in
        return true;
      }

      return true;
    },
    async jwt({ token, user, account }) {
      if (user) {
        // For credentials sign-in the authorize() function already returns the DB uuid as user.id
        token.id = user.id;
      }

      // For Google sign-in, user.id is the Google sub ID, not our DB uuid.
      // Look up the DB record by email to get the correct uuid.
      if (account?.provider === "google" && token.email) {
        const [dbUser] = await db
          .select({ id: users.id })
          .from(users)
          .where(eq(users.email, token.email))
          .limit(1);

        if (dbUser) {
          token.id = dbUser.id;
        }
      }

      return token;
    },
    async session({ session, token }) {
      if (token.id) {
        session.user.id = token.id as string;
      }
      return session;
    },
  },
});
