import { NextRequest, NextResponse } from 'next/server'; import { projectService } from '@/lib/prisma'; import { analyticsCache } from '@/lib/redis'; import { requireSessionAuth, checkRateLimit, getRateLimitHeaders } from '@/lib/auth'; export async function GET(request: NextRequest) { try { // Rate limiting - more generous for admin dashboard const ip = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || 'unknown'; if (!checkRateLimit(ip, 20, 60000)) { // 20 requests per minute return new NextResponse( JSON.stringify({ error: 'Rate limit exceeded' }), { status: 429, headers: { 'Content-Type': 'application/json', ...getRateLimitHeaders(ip, 5, 60000) } } ); } // Check admin authentication - for admin dashboard requests, we trust the session // The middleware has already verified the admin session for /manage routes const isAdminRequest = request.headers.get('x-admin-request') === 'true'; if (!isAdminRequest) { const authError = requireSessionAuth(request); if (authError) { return authError; } } // Check cache first const cachedStats = await analyticsCache.getOverallStats(); if (cachedStats) { return NextResponse.json(cachedStats); } // Get analytics data const projectsResult = await projectService.getAllProjects(); const projects = projectsResult.projects || projectsResult; const performanceStats = await projectService.getPerformanceStats(); // Calculate analytics metrics const analytics = { overview: { totalProjects: projects.length, publishedProjects: projects.filter(p => p.published).length, featuredProjects: projects.filter(p => p.featured).length, totalViews: projects.reduce((sum, p) => sum + ((p.analytics as Record)?.views as number || 0), 0), totalLikes: projects.reduce((sum, p) => sum + ((p.analytics as Record)?.likes as number || 0), 0), totalShares: projects.reduce((sum, p) => sum + ((p.analytics as Record)?.shares as number || 0), 0), avgLighthouse: projects.length > 0 ? Math.round(projects.reduce((sum, p) => sum + ((p.performance as Record)?.lighthouse as number || 0), 0) / projects.length) : 0 }, projects: projects.map(project => ({ id: project.id, title: project.title, category: project.category, difficulty: project.difficulty, views: (project.analytics as Record)?.views as number || 0, likes: (project.analytics as Record)?.likes as number || 0, shares: (project.analytics as Record)?.shares as number || 0, lighthouse: (project.performance as Record)?.lighthouse as number || 0, published: project.published, featured: project.featured, createdAt: project.createdAt, updatedAt: project.updatedAt })), categories: performanceStats.byCategory, difficulties: performanceStats.byDifficulty, performance: { avgLighthouse: performanceStats.avgLighthouse, totalViews: performanceStats.totalViews, totalLikes: performanceStats.totalLikes, totalShares: performanceStats.totalShares } }; // Cache the results await analyticsCache.setOverallStats(analytics); return NextResponse.json(analytics); } catch (error) { console.error('Analytics dashboard error:', error); return NextResponse.json( { error: 'Failed to fetch analytics data' }, { status: 500 } ); } }