import { NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import connectDB from '@/lib/mongodb' import TopicModel from '@/models/topic' import { authMiddleware } from '@/lib/auth-middleware' // Response schema for type safety const DashboardStatsSchema = z.object({ success: z.boolean(), data: z.object({ stats: z.object({ totalTopics: z.number(), publishedTopics: z.number(), draftTopics: z.number(), totalViews: z.number(), }), userTopics: z.array( z.object({ id: z.string(), title: z.string(), slug: z.string(), publishedAt: z.number(), isDraft: z.boolean(), views: z.number().optional(), excerpt: z.string(), tags: z.array( z.object({ name: z.string(), }) ), }) ), }), }) export type DashboardResponse = z.infer export async function GET(request: NextRequest) { try { // Authenticate user const user = await authMiddleware(request) if (!user) { return NextResponse.json( { success: false, error: { message: 'Authentication required', code: 'UNAUTHORIZED' }, }, { status: 401 } ) } // Connect to database await connectDB() // MongoDB Aggregation Pipeline for user topic statistics const userTopics = await TopicModel.aggregate([ { // Match topics by user ownership $match: { authorId: user.id, }, }, { // Sort by publication date (newest first) $sort: { publishedAt: -1, }, }, { // Project only the fields we need for the dashboard $project: { id: '$id', title: '$title', slug: '$slug', publishedAt: '$publishedAt', isDraft: '$isDraft', views: { $ifNull: ['$views', 0] }, // Default to 0 if views field doesn't exist excerpt: '$excerpt', tags: { $map: { input: '$tags', as: 'tag', in: { name: '$$tag.name', }, }, }, }, }, ]) // Calculate statistics from the aggregated data const totalTopics = userTopics.length const publishedTopics = userTopics.filter((topic) => !topic.isDraft).length const draftTopics = userTopics.filter((topic) => topic.isDraft).length const totalViews = userTopics.reduce((sum, topic) => sum + (topic.views || 0), 0) // Prepare response data const responseData = { success: true, data: { stats: { totalTopics, publishedTopics, draftTopics, totalViews, }, userTopics, }, } // Validate response format matches frontend expectations const validatedResponse = DashboardStatsSchema.parse(responseData) return NextResponse.json(validatedResponse, { status: 200 }) } catch (error) { console.error('Dashboard API error:', error) if (error instanceof z.ZodError) { return NextResponse.json( { success: false, error: { message: 'Invalid response format', code: 'VALIDATION_ERROR' }, }, { status: 500 } ) } return NextResponse.json( { success: false, error: { message: 'Failed to fetch dashboard data', code: 'INTERNAL_ERROR' }, }, { status: 500 } ) } }