import { FieldValue } from 'firebase-admin/firestore'; import { getAdminDb } from '@/lib/firebase/admin'; import type { ProjectPhase, ProjectPhaseData, ProjectPhaseScores, ProjectStage, } from '@/lib/types/project-artifacts'; export const clamp = (value: number) => Math.max(0, Math.min(1, value)); export const nowIso = () => new Date().toISOString(); export function uniqueStrings(values: Array): string[] { return Array.from(new Set(values.filter((value): value is string => Boolean(value)))); } export function toStage(stage?: string | null): ProjectStage { const allowed: ProjectStage[] = ['idea', 'prototype', 'mvp_in_progress', 'live_beta', 'live_paid', 'unknown']; if (!stage) return 'unknown'; return allowed.includes(stage as ProjectStage) ? (stage as ProjectStage) : 'unknown'; } export async function loadPhaseContainers(projectId: string) { const adminDb = getAdminDb(); const projectRef = adminDb.collection('projects').doc(projectId); const snapshot = await projectRef.get(); const doc = snapshot.data() || {}; const phaseData = (doc.phaseData ?? {}) as ProjectPhaseData; const phaseScores = (doc.phaseScores ?? {}) as ProjectPhaseScores; const phaseHistory = Array.isArray(doc.phaseHistory) ? [...doc.phaseHistory] : []; return { projectRef, phaseData, phaseScores, phaseHistory }; } interface PersistencePayload { phaseData: ProjectPhaseData; phaseScores: ProjectPhaseScores; phaseHistory: Array>; nextPhase?: ProjectPhase; } export async function persistPhaseArtifacts( projectId: string, builder: ( phaseData: ProjectPhaseData, phaseScores: ProjectPhaseScores, phaseHistory: Array>, ) => PersistencePayload, ) { const { projectRef, phaseData, phaseScores, phaseHistory } = await loadPhaseContainers(projectId); const payload = builder(phaseData, phaseScores, phaseHistory); await projectRef.set( { phaseData: payload.phaseData, phaseScores: payload.phaseScores, phaseHistory: payload.phaseHistory, ...(payload.nextPhase ? { currentPhase: payload.nextPhase, phaseStatus: 'completed' as const } : {}), updatedAt: FieldValue.serverTimestamp(), }, { merge: true }, ); }