import { NextRequest, NextResponse } from 'next/server'; import { adminDb } from '@/lib/firebase/admin'; export async function GET(request: NextRequest) { try { const projectId = request.nextUrl.searchParams.get('projectId'); const sessionGapMinutes = parseInt(request.nextUrl.searchParams.get('gap') || '120'); // 2 hours default if (!projectId) { return NextResponse.json({ error: 'Missing projectId' }, { status: 400 }); } // Get all conversations sorted by time const conversationsSnapshot = await adminDb .collection('projects') .doc(projectId) .collection('cursorConversations') .orderBy('createdAt', 'asc') .get(); const conversations = conversationsSnapshot.docs.map(doc => { const data = doc.data(); return { id: doc.id, name: data.name, createdAt: new Date(data.createdAt), relevanceScore: data.relevanceScore || 0 }; }); // Group into sessions based on time gaps const sessions: any[] = []; let currentSession: any = null; for (const conv of conversations) { if (!currentSession) { // Start first session currentSession = { startTime: conv.createdAt, endTime: conv.createdAt, conversations: [conv], relevanceScores: [conv.relevanceScore] }; } else { // Check time gap from last conversation const gapMs = conv.createdAt.getTime() - currentSession.endTime.getTime(); const gapMinutes = gapMs / (1000 * 60); if (gapMinutes <= sessionGapMinutes) { // Same session currentSession.conversations.push(conv); currentSession.relevanceScores.push(conv.relevanceScore); currentSession.endTime = conv.createdAt; } else { // New session - close current and start new sessions.push(currentSession); currentSession = { startTime: conv.createdAt, endTime: conv.createdAt, conversations: [conv], relevanceScores: [conv.relevanceScore] }; } } } // Add last session if (currentSession) { sessions.push(currentSession); } // Analyze each session const analyzedSessions = sessions.map((session, idx) => { const durationMinutes = Math.round((session.endTime.getTime() - session.startTime.getTime()) / (1000 * 60)); // Calculate session relevance score (average of all conversations) const avgScore = session.relevanceScores.reduce((a: number, b: number) => a + b, 0) / session.relevanceScores.length; // Count negative/positive conversations const negative = session.relevanceScores.filter((s: number) => s < 0).length; const positive = session.relevanceScores.filter((s: number) => s > 0).length; const neutral = session.relevanceScores.filter((s: number) => s === 0).length; // Determine likely project based on majority let likelyProject = 'unknown'; if (negative > positive && negative > neutral) { likelyProject = 'other (NHL/market)'; } else if (positive > negative && positive > neutral) { likelyProject = 'vibn (likely)'; } else if (positive > 0 || avgScore > 0) { likelyProject = 'vibn (mixed)'; } else { likelyProject = 'unclear'; } return { sessionNumber: idx + 1, startTime: session.startTime.toISOString(), endTime: session.endTime.toISOString(), durationMinutes, conversationCount: session.conversations.length, avgRelevanceScore: Math.round(avgScore * 100) / 100, scoreBreakdown: { negative, neutral, positive }, likelyProject, conversationNames: session.conversations.slice(0, 5).map((c: any) => c.name) }; }); return NextResponse.json({ totalConversations: conversations.length, totalSessions: sessions.length, sessionGapMinutes, sessions: analyzedSessions }); } catch (error) { console.error('Error analyzing sessions:', error); return NextResponse.json( { error: 'Failed to analyze sessions', details: error instanceof Error ? error.message : String(error) }, { status: 500 } ); } }