import { NextRequest, NextResponse } from 'next/server'; import { z } from 'zod'; import { prisma } from '@/lib/db'; import { hashPassword, signToken, setSessionCookie } from '@/lib/auth'; import { provisionGHLForUser } from '@/lib/ghl'; import { adminTaggingService } from '@/lib/ghl'; import { Role } from '@/types'; const signupSchema = z.object({ email: z.string().email(), password: z.string().min(8), firstName: z.string().min(1), lastName: z.string().min(1), }); export async function POST(request: NextRequest) { try { const body = await request.json(); const validated = signupSchema.parse(body); // Check if user already exists const existingUser = await prisma.user.findUnique({ where: { email: validated.email }, }); if (existingUser) { return NextResponse.json( { error: 'User with this email already exists' }, { status: 409 } ); } // Hash password const passwordHash = await hashPassword(validated.password); // Create user const user = await prisma.user.create({ data: { email: validated.email, passwordHash, firstName: validated.firstName, lastName: validated.lastName, role: Role.USER, }, }); // Create initial setup status await prisma.setupStatus.create({ data: { userId: user.id }, }); // Provision GHL sub-account (async, don't block signup) provisionGHLForUser({ userId: user.id, email: user.email, firstName: validated.firstName, lastName: validated.lastName, }).catch(err => console.error('GHL provisioning failed:', err)); // Generate token const token = signToken({ userId: user.id, email: user.email, role: user.role as Role, }); // Set session cookie await setSessionCookie(token); return NextResponse.json({ success: true, user: { id: user.id, email: user.email, firstName: user.firstName, lastName: user.lastName, role: user.role, }, token, }, { status: 201 }); } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( { error: 'Validation failed', details: error.issues }, { status: 400 } ); } console.error('Signup error:', error); return NextResponse.json( { error: 'Internal server error' }, { status: 500 } ); } }