import { NextResponse } from 'next/server'; import { getAdminAuth, getAdminDb } from '@/lib/firebase/admin'; import { FieldValue } from 'firebase-admin/firestore'; import type { ProjectPhaseData, ProjectPhaseScores } from '@/lib/types/project-artifacts'; export async function POST(request: Request) { try { const authHeader = request.headers.get('Authorization'); if (!authHeader?.startsWith('Bearer ')) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const idToken = authHeader.split('Bearer ')[1]; const adminAuth = getAdminAuth(); const adminDb = getAdminDb(); let userId: string; try { const decodedToken = await adminAuth.verifyIdToken(idToken); userId = decodedToken.uid; } catch (error) { return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); } const body = await request.json(); const { projectName, projectType, slug, vision, product, workspacePath, // Optional: if coming from association prompt chatgptUrl, // Optional: if from ChatGPT githubRepo, // Optional: if from GitHub githubRepoId, githubRepoUrl, githubDefaultBranch, } = body; // Check if slug is available const existingProject = await adminDb .collection('projects') .where('slug', '==', slug) .limit(1) .get(); if (!existingProject.empty) { return NextResponse.json( { error: 'Project slug already exists' }, { status: 400 } ); } // Get user data const userDoc = await adminDb.collection('users').doc(userId).get(); const userData = userDoc.data(); const workspace = userData?.workspace || 'my-workspace'; // Create project const projectRef = adminDb.collection('projects').doc(); await projectRef.set({ id: projectRef.id, name: projectName, slug, userId, workspace, projectType, productName: product.name, productVision: vision || '', isForClient: product.isForClient || false, hasLogo: product.hasLogo || false, hasDomain: product.hasDomain || false, hasWebsite: product.hasWebsite || false, hasGithub: !!githubRepo, hasChatGPT: !!chatgptUrl, workspacePath: workspacePath || null, workspaceName: workspacePath ? workspacePath.split('/').pop() : null, // GitHub data githubRepo: githubRepo || null, githubRepoId: githubRepoId || null, githubRepoUrl: githubRepoUrl || null, githubDefaultBranch: githubDefaultBranch || null, // ChatGPT data chatgptUrl: chatgptUrl || null, // Extension tracking extensionLinked: false, status: 'active', // Pipeline tracking currentPhase: 'collector', phaseStatus: 'not_started', phaseData: {} as ProjectPhaseData, phaseScores: {} as ProjectPhaseScores, createdAt: FieldValue.serverTimestamp(), updatedAt: FieldValue.serverTimestamp(), }); console.log(`[API] Created project ${projectRef.id} (${slug})`); // If workspacePath provided, associate existing sessions if (workspacePath) { const sessionsSnapshot = await adminDb .collection('sessions') .where('userId', '==', userId) .where('workspacePath', '==', workspacePath) .where('needsProjectAssociation', '==', true) .get(); if (!sessionsSnapshot.empty) { const batch = adminDb.batch(); sessionsSnapshot.docs.forEach((doc) => { batch.update(doc.ref, { projectId: projectRef.id, needsProjectAssociation: false, updatedAt: FieldValue.serverTimestamp(), }); }); await batch.commit(); console.log(`[API] Associated ${sessionsSnapshot.size} sessions with project`); } } return NextResponse.json({ success: true, projectId: projectRef.id, slug, workspace, }); } catch (error) { console.error('Error creating project:', error); return NextResponse.json( { error: 'Failed to create project', details: error instanceof Error ? error.message : String(error), }, { status: 500 } ); } }