import { NextRequest, NextResponse } from 'next/server' import connectDB from '@/lib/mongodb' import TopicModel, { transformToTopics } from '@/models/topic' import { authMiddleware } from '@/lib/auth-middleware' import { ZodError } from 'zod' export async function GET(request: NextRequest) { try { await connectDB() const searchParams = request.nextUrl.searchParams const page = parseInt(searchParams.get('page') || '1') const limit = parseInt(searchParams.get('limit') || '10') const search = searchParams.get('q') || '' const tag = searchParams.get('tag') || '' const authorId = searchParams.get('authorId') || '' // For filtering by user's topics const includeDrafts = searchParams.get('includeDrafts') === 'true' // For user's own topics const fetchAll = searchParams.get('fetchAll') // Admin panel support const skip = (page - 1) * limit // Build query based on parameters const query: any = {} // Authentication check for private operations (drafts or admin) let user = null try { user = await authMiddleware(request) } catch (error) { // Non-authenticated request - that's okay for public topic listing } // If requesting user's own topics with drafts, verify authentication if (includeDrafts && !user) { return NextResponse.json( { success: false, error: { message: 'Authentication required to view drafts', code: 'AUTH_REQUIRED' }, }, { status: 401 } ) } // Filter by author if specified if (authorId) { query.authorId = authorId } // Handle draft filtering if (fetchAll === 'true') { // Admin panel - show all posts (drafts and published) // No draft filtering applied } else if (includeDrafts && user && (authorId === user.id || !authorId)) { // User requesting their own topics (including drafts) if (!authorId) { query.authorId = user.id } } else { // Public topic listing - only published topics query.isDraft = false } // Search functionality if (search) { query.$or = [ { title: { $regex: search, $options: 'i' } }, { excerpt: { $regex: search, $options: 'i' } }, { content: { $regex: search, $options: 'i' } }, ] } // Filter by tag if (tag) { query['tags.name'] = { $regex: new RegExp(tag, 'i') } } // Get total count with same filters const totalTopics = await TopicModel.countDocuments(query) // Get paginated topics sorted by publishedAt const topics = await TopicModel.find(query) .sort({ publishedAt: -1 }) .skip(skip) .limit(limit) .lean() if (!topics || topics.length === 0) { return NextResponse.json( { success: true, data: [], pagination: { total: 0, page, limit, totalPages: 0, }, }, { status: 200 } ) } // Transform the topics using our utility function const transformedTopics = transformToTopics(topics) return NextResponse.json( { success: true, data: transformedTopics, pagination: { total: totalTopics, page, limit, totalPages: Math.ceil(totalTopics / limit), }, }, { status: 200 } ) } catch (error) { console.error('Error fetching topics:', error) if (error instanceof ZodError) { return NextResponse.json( { success: false, error: { message: 'Data validation failed', code: 'VALIDATION_ERROR', details: error.issues, }, }, { status: 400 } ) } return NextResponse.json( { success: false, error: { message: 'Failed to fetch topics', code: 'SERVER_ERROR' }, }, { status: 500 } ) } }