import { NextRequest, NextResponse } from 'next/server' import prisma from '@/lib/prisma' import { auth } from '@/auth' import { z } from 'zod' import crypto from 'crypto' import { verifyParticipant, logActivity } from '@/lib/brainstorm-collab' const inviteSchema = z.object({ role: z.enum(['editor', 'viewer']).default('editor'), expiresInHours: z.number().min(1).max(168).default(24), email: z.string().email().optional(), }) export async function POST( request: NextRequest, { params }: { params: Promise<{ sessionId: string }> } ) { const session = await auth() if (!session?.user?.id) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } try { const { sessionId } = await params const { isParticipant } = await verifyParticipant(sessionId, session.user.id, 'host') if (!isParticipant) { return NextResponse.json({ error: 'Only the host can invite' }, { status: 403 }) } const body = await request.json() const { role: inviteRole, expiresInHours, email } = inviteSchema.parse(body) const brainstormSession = await prisma.brainstormSession.findUnique({ where: { id: sessionId }, select: { id: true, seedIdea: true, userId: true, inviteToken: true, inviteExpiry: true }, }) if (!brainstormSession) { return NextResponse.json({ error: 'Session not found' }, { status: 404 }) } let token = brainstormSession.inviteToken let expiry = brainstormSession.inviteExpiry if (!token || (expiry && expiry < new Date())) { token = crypto.randomBytes(24).toString('hex') expiry = new Date(Date.now() + expiresInHours * 60 * 60 * 1000) await prisma.brainstormSession.update({ where: { id: sessionId }, data: { inviteToken: token, inviteExpiry: expiry }, }) } const inviteUrl = `/brainstorm?invite=${token}` if (email) { const recipient = await prisma.user.findUnique({ where: { email }, select: { id: true, name: true, email: true }, }) if (!recipient) { return NextResponse.json({ error: 'User not found' }, { status: 404 }) } if (recipient.id === session.user.id) { return NextResponse.json({ error: 'Cannot invite yourself' }, { status: 400 }) } const existing = await prisma.brainstormParticipant.findFirst({ where: { sessionId, userId: recipient.id }, }) if (existing) { return NextResponse.json({ error: 'Already a participant' }, { status: 409 }) } await prisma.notification.create({ data: { userId: recipient.id, type: 'brainstorm_invite', title: brainstormSession.seedIdea.length > 50 ? brainstormSession.seedIdea.substring(0, 50) + '…' : brainstormSession.seedIdea, message: `${session.user.name || 'Someone'} invited you to a brainstorm session`, actionUrl: inviteUrl, relatedId: sessionId, }, }) await logActivity(sessionId, 'invite_created', session.user.id, { role: inviteRole, targetEmail: email, targetUserId: recipient.id, }) return NextResponse.json({ success: true, mode: 'email', invitedUser: { name: recipient.name, email: recipient.email }, inviteUrl, expiresAt: expiry, }) } await logActivity(sessionId, 'invite_created', session.user.id, { role: inviteRole }) return NextResponse.json({ success: true, mode: 'link', inviteUrl, token, expiresAt: expiry, }) } catch (error: any) { if (error instanceof z.ZodError) { return NextResponse.json({ error: error.issues }, { status: 400 }) } console.error('Error creating invite:', error) return NextResponse.json({ error: 'Failed to create invite' }, { status: 500 }) } }