import { NextRequest, NextResponse } from 'next/server' import { getGoogleUser } from '@/lib/google-oauth' import { generateTokens } from '@/lib/jwt' import connectDB from '@/lib/mongodb' import { User } from '@/models/user' import { appConfig } from '@/lib/env' export async function GET(request: NextRequest) { try { const { searchParams } = new URL(request.url) const code = searchParams.get('code') const state = searchParams.get('state') const error = searchParams.get('error') // Handle OAuth errors if (error) { return NextResponse.redirect( new URL(`/auth?error=${encodeURIComponent(error)}`, appConfig.appUrl) ) } // Validate required parameters if (!code || state !== 'google_oauth') { return NextResponse.redirect(new URL('/auth?error=invalid_oauth_callback', appConfig.appUrl)) } // Get user info from Google const googleUser = await getGoogleUser(code) // Connect to database await connectDB() // Check if user exists let user = await User.findOne({ $or: [ { email: googleUser.email.toLowerCase() }, { providerId: googleUser.id, provider: 'google' }, ], }) if (!user) { // Create new user user = new User({ email: googleUser.email.toLowerCase(), name: googleUser.name, provider: 'google', providerId: googleUser.id, avatar: googleUser.picture || undefined, isVerified: googleUser.verified_email, lastLogin: new Date(), }) } else { // Update existing user with Google info (preserve original provider) // Only link Google if user doesn't already have a local account if (user.provider !== 'local') { user.provider = 'google' user.providerId = googleUser.id } else { // For local users, just add Google info without changing provider if (!user.providerId) { user.providerId = googleUser.id } } // Update other info safely user.name = googleUser.name user.isVerified = googleUser.verified_email || user.isVerified user.lastLogin = new Date() // Update avatar only if user doesn't have one if (googleUser.picture && !user.avatar) { user.avatar = googleUser.picture } } // Generate tokens const { accessToken, refreshToken } = generateTokens({ userId: user._id.toString(), email: user.email, role: user.role, }) // Update user's refresh token user.refreshToken = refreshToken await user.save() // Create redirect response using the public app URL const redirectURL = new URL('/dashboard', appConfig.appUrl) const response = NextResponse.redirect(redirectURL) // Set HTTP-only cookies response.cookies.set('accessToken', accessToken, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', maxAge: 15 * 60, // 15 minutes path: '/', }) response.cookies.set('refreshToken', refreshToken, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', maxAge: 7 * 24 * 60 * 60, // 7 days path: '/', }) return response } catch (error) { console.error('Google OAuth callback error:', error) return NextResponse.redirect(new URL('/auth?error=oauth_callback_failed', appConfig.appUrl)) } }