import { NextResponse } from 'next/server'; import { prisma } from '@/lib/db'; import { getCurrentAdmin, AdminPermission, hasPermission } from '@/lib/admin-auth'; export const runtime = 'nodejs'; export async function GET(request: Request) { try { const admin = await getCurrentAdmin(request as any); if (!admin || !hasPermission(admin, AdminPermission.READ_ANALYTICS)) { return NextResponse.json( { error: 'Unauthorized' }, { status: 401 } ); } const url = new URL(request.url); const period = url.searchParams.get('period') || '30'; // days const periodDays = parseInt(period); const startDate = new Date(); startDate.setDate(startDate.getDate() - periodDays); // User registration timeline (last 30 days) const registrationTimeline = await Promise.all( Array.from({ length: periodDays }, (_, i) => { const date = new Date(); date.setDate(date.getDate() - i); return date.toISOString().split('T')[0]; }).reverse().map(async (date) => { const startOfDay = new Date(date + 'T00:00:00.000Z'); const endOfDay = new Date(date + 'T23:59:59.999Z'); const registrations = await prisma.user.count({ where: { createdAt: { gte: startOfDay, lte: endOfDay } } }); return { date, registrations }; }) ); // User activity patterns (login frequency) const userActivityPatterns = await prisma.user.findMany({ select: { id: true, email: true, name: true, role: true, createdAt: true, lastLoginAt: true, _count: { select: { chatConversations: true, prayerRequests: true, bookmarks: true, notes: true } } }, orderBy: { lastLoginAt: 'desc' }, take: 100 }); // Most active users (by total activity) const mostActiveUsers = userActivityPatterns .map(user => ({ ...user, totalActivity: user._count.chatConversations + user._count.prayerRequests + user._count.bookmarks + user._count.notes })) .sort((a, b) => b.totalActivity - a.totalActivity) .slice(0, 20); // User retention analysis const thirtyDaysAgo = new Date(); thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); const newUsersLast30Days = await prisma.user.count({ where: { createdAt: { gte: thirtyDaysAgo } } }); const activeUsersLast30Days = await prisma.user.count({ where: { createdAt: { gte: thirtyDaysAgo }, lastLoginAt: { gte: sevenDaysAgo } } }); const retentionRate = newUsersLast30Days > 0 ? (activeUsersLast30Days / newUsersLast30Days) * 100 : 0; // User engagement by feature const featureUsage = { chat: await prisma.chatConversation.count({ where: { createdAt: { gte: startDate } } }), prayers: await prisma.prayerRequest.count({ where: { createdAt: { gte: startDate } } }), bookmarks: await prisma.bookmark.count({ where: { createdAt: { gte: startDate } } }), notes: await prisma.note.count({ where: { createdAt: { gte: startDate } } }) }; // User demographics (by role and creation time) const userDemographics = await prisma.user.groupBy({ by: ['role'], _count: { role: true }, _min: { createdAt: true }, _max: { createdAt: true } }); // Session length analysis (approximate based on conversation activity) const sessionAnalysis = await prisma.chatConversation.findMany({ select: { userId: true, createdAt: true, lastMessageAt: true, _count: { select: { messages: true } } }, where: { createdAt: { gte: startDate }, userId: { not: null } }, orderBy: { lastMessageAt: 'desc' }, take: 1000 }); const avgSessionLength = sessionAnalysis.reduce((acc, session) => { const duration = new Date(session.lastMessageAt).getTime() - new Date(session.createdAt).getTime(); return acc + (duration / 1000 / 60); // minutes }, 0) / sessionAnalysis.length || 0; const avgMessagesPerSession = sessionAnalysis.reduce((acc, session) => { return acc + session._count.messages; }, 0) / sessionAnalysis.length || 0; return NextResponse.json({ period: periodDays, timeline: { registrations: registrationTimeline }, activity: { patterns: userActivityPatterns.slice(0, 50), // Limit for performance mostActive: mostActiveUsers }, retention: { rate: Math.round(retentionRate * 100) / 100, newUsers: newUsersLast30Days, activeUsers: activeUsersLast30Days }, engagement: { featureUsage, avgSessionLength: Math.round(avgSessionLength * 100) / 100, avgMessagesPerSession: Math.round(avgMessagesPerSession * 100) / 100 }, demographics: userDemographics }); } catch (error) { console.error('Admin user analytics error:', error); return NextResponse.json( { error: 'Server error' }, { status: 500 } ); } }