import { collection, doc, getDoc, getDocs, setDoc, updateDoc, query, where, orderBy, Timestamp, addDoc, deleteDoc, } from 'firebase/firestore'; import { db } from './firebase'; import type { User, AgentSettings, CallTask, CallAttempt, CallRecord, CreditTransaction, NotificationSettings, BookedAppointment, DefaultLimits, Purchase, } from './types'; // Users export const getUser = async (uid: string): Promise => { const docRef = doc(db, 'users', uid); const docSnap = await getDoc(docRef); return docSnap.exists() ? (docSnap.data() as User) : null; }; export const updateUserCredits = async (uid: string, newBalance: number) => { const docRef = doc(db, 'users', uid); await updateDoc(docRef, { creditBalance: newBalance, updatedAt: Timestamp.now(), }); }; export const updateUserOnboardingCompleted = async (uid: string, completed: boolean) => { const docRef = doc(db, 'users', uid); await updateDoc(docRef, { onboardingCompleted: completed, updatedAt: Timestamp.now(), }); }; // Agent Settings export const getAgentSettings = async (userId: string): Promise => { const docRef = doc(db, 'agentSettings', userId); const docSnap = await getDoc(docRef); if (docSnap.exists()) { return docSnap.data() as AgentSettings; } // Create default if not exists const defaults: AgentSettings = { userId, agentName: 'HolaCompi', appLanguage: 'English', primaryCallLanguage: 'English', secondaryCallLanguages: [], tone: 'Friendly', agentInstructions: 'You are HolaCompi, a helpful Spanish friend who makes phone calls on behalf of users.', createdAt: Timestamp.now(), updatedAt: Timestamp.now(), }; await setDoc(docRef, defaults); return defaults; }; export const updateAgentSettings = async (userId: string, updates: Partial) => { const docRef = doc(db, 'agentSettings', userId); await updateDoc(docRef, { ...updates, updatedAt: Timestamp.now(), }); }; // Call Tasks export const createCallTask = async (task: Omit): Promise => { const docRef = await addDoc(collection(db, 'callTasks'), task); return docRef.id; }; export const getCallTasks = async (userId: string): Promise => { const q = query( collection(db, 'callTasks'), where('userId', '==', userId), orderBy('scheduledAt', 'desc') ); const snapshot = await getDocs(q); return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as CallTask)); }; export const getCallTask = async (taskId: string): Promise => { const docRef = doc(db, 'callTasks', taskId); const docSnap = await getDoc(docRef); return docSnap.exists() ? ({ id: docSnap.id, ...docSnap.data() } as CallTask) : null; }; export const updateCallTask = async (taskId: string, updates: Partial) => { const docRef = doc(db, 'callTasks', taskId); await updateDoc(docRef, { ...updates, updatedAt: Timestamp.now(), }); }; export const deleteCallTask = async (taskId: string) => { await deleteDoc(doc(db, 'callTasks', taskId)); }; // Call Attempts export const createCallAttempt = async ( taskId: string, attempt: Omit ): Promise => { const docRef = await addDoc( collection(db, 'callTasks', taskId, 'attempts'), attempt ); return docRef.id; }; export const getCallAttempts = async (taskId: string): Promise => { const q = query( collection(db, 'callTasks', taskId, 'attempts'), orderBy('startTime', 'desc') ); const snapshot = await getDocs(q); return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as CallAttempt)); }; export const updateCallAttempt = async ( taskId: string, attemptId: string, updates: Partial ) => { const docRef = doc(db, 'callTasks', taskId, 'attempts', attemptId); await updateDoc(docRef, updates); }; // Calls export const createCallRecord = async ( record: Omit ): Promise => { const docRef = await addDoc(collection(db, 'calls'), { ...record, createdAt: Timestamp.now(), updatedAt: Timestamp.now(), }); return docRef.id; }; export const updateCallRecord = async ( callId: string, updates: Partial ) => { const docRef = doc(db, 'calls', callId); await updateDoc(docRef, { ...updates, updatedAt: Timestamp.now() }); }; export const getCallByVapiCallId = async (vapiCallId: string): Promise => { const q = query(collection(db, 'calls'), where('vapiCallId', '==', vapiCallId)); const snapshot = await getDocs(q); if (snapshot.empty) return null; const docSnap = snapshot.docs[0]; return { id: docSnap.id, ...(docSnap.data() as CallRecord) }; }; // Credit Transactions export const createCreditTransaction = async ( transaction: Omit ): Promise => { const docRef = await addDoc(collection(db, 'creditLedger'), transaction); return docRef.id; }; export const getCreditTransactions = async (userId: string): Promise => { const q = query( collection(db, 'creditLedger'), where('userId', '==', userId), orderBy('createdAt', 'desc') ); const snapshot = await getDocs(q); return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as CreditTransaction)); }; // Purchases export const createPurchase = async (purchase: Omit): Promise => { const docRef = await addDoc(collection(db, 'purchases'), purchase); return docRef.id; }; export const getPurchasesByUser = async (userId: string): Promise => { const q = query( collection(db, 'purchases'), where('userId', '==', userId), orderBy('createdAt', 'desc') ); const snapshot = await getDocs(q); return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as Purchase)); }; // Notification Settings export const getNotificationSettings = async (userId: string): Promise => { const docRef = doc(db, 'notificationSettings', userId); const docSnap = await getDoc(docRef); if (docSnap.exists()) { return docSnap.data() as NotificationSettings; } const defaults: NotificationSettings = { userId, notifyOnSuccess: true, notifyOnFailure: true, emailSummary: false, autoAddToCalendar: false, googleCalendarConnected: false, iCloudCalendarConnected: false, createdAt: Timestamp.now(), updatedAt: Timestamp.now(), }; await setDoc(docRef, defaults); return defaults; }; export const updateNotificationSettings = async ( userId: string, updates: Partial ) => { const docRef = doc(db, 'notificationSettings', userId); await updateDoc(docRef, { ...updates, updatedAt: Timestamp.now(), }); }; // Booked Appointments export const createBookedAppointment = async ( appointment: Omit ): Promise => { const docRef = await addDoc(collection(db, 'bookedAppointments'), appointment); return docRef.id; }; export const getBookedAppointments = async (userId: string): Promise => { const q = query( collection(db, 'bookedAppointments'), where('userId', '==', userId), orderBy('dateTime', 'asc') ); const snapshot = await getDocs(q); return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() } as BookedAppointment)); }; // Default Limits export const getDefaultLimits = async (userId: string): Promise => { const docRef = doc(db, 'defaultLimits', userId); const docSnap = await getDoc(docRef); if (docSnap.exists()) { return docSnap.data() as DefaultLimits; } const defaults: DefaultLimits = { userId, defaultMaxMinutes: 10, defaultMaxCredits: 10, allowAutoExtension: false, maxExtraMinutes: 0, defaultMaxRecalls: 2, minDelayBetweenRecalls: 15, updatedAt: Timestamp.now(), }; await setDoc(docRef, defaults); return defaults; }; export const updateDefaultLimits = async (userId: string, updates: Partial) => { const docRef = doc(db, 'defaultLimits', userId); await updateDoc(docRef, { ...updates, updatedAt: Timestamp.now(), }); };