import { getEnvVar, isTest } from '../../utils/env'; import { MockDatabaseStrategy } from './MockDatabaseStrategy'; import { ProductionDatabaseStrategy } from './ProductionDatabaseStrategy'; import { DatabaseStrategy } from './types'; import { AccountStatus } from '../auth/auth.constants'; /** * Consolidated Database Service * Uses strategy pattern to switch between mock and production implementations */ export class DatabaseService implements DatabaseStrategy { private strategy: DatabaseStrategy; constructor() { this.strategy = this.createStrategy(); } private createStrategy(): DatabaseStrategy { // Always use mock service in test environment if (isTest()) { return new MockDatabaseStrategy(); } // Check if we're in a Docker environment or if CouchDB URL is configured const couchdbUrl = getEnvVar('VITE_COUCHDB_URL') || getEnvVar('COUCHDB_URL'); const useProduction = !!couchdbUrl && couchdbUrl !== 'mock'; if (useProduction) { try { return new ProductionDatabaseStrategy(); } catch (error) { console.warn( 'Production CouchDB service not available, falling back to mock:', error ); return new MockDatabaseStrategy(); } } else { return new MockDatabaseStrategy(); } } // Delegate all methods to the strategy // User operations async createUser(user: Parameters[0]) { return this.strategy.createUser(user); } async updateUser(user: Parameters[0]) { return this.strategy.updateUser(user); } async getUserById(id: string) { return this.strategy.getUserById(id); } async findUserByEmail(email: string) { return this.strategy.findUserByEmail(email); } async deleteUser(id: string) { return this.strategy.deleteUser(id); } async getAllUsers() { return this.strategy.getAllUsers(); } // Medication operations async createMedication( userId: string, medication: Parameters[1] ) { return this.strategy.createMedication(userId, medication); } // Overloads for updateMedication async updateMedication( medication: Parameters[0] ): Promise[0]> { return this.strategy.updateMedication(medication); } async getMedications(userId: string) { return this.strategy.getMedications(userId); } async deleteMedication(id: string): Promise { return this.strategy.deleteMedication(id); } // User settings operations async getUserSettings(userId: string) { return this.strategy.getUserSettings(userId); } async updateUserSettings( settings: Parameters[0] ) { return this.strategy.updateUserSettings(settings); } // Taken doses operations async getTakenDoses(userId: string) { return this.strategy.getTakenDoses(userId); } // Overloads for updateTakenDoses async updateTakenDoses( takenDoses: Parameters[0] ): Promise[0]> { return this.strategy.updateTakenDoses(takenDoses); } // Custom reminders operations async createCustomReminder( userId: string, reminder: Parameters[1] ) { return this.strategy.createCustomReminder(userId, reminder); } // Overloads for updateCustomReminder async updateCustomReminder( reminder: Parameters[0] ): Promise[0]> { return this.strategy.updateCustomReminder(reminder); } async getCustomReminders(userId: string) { return this.strategy.getCustomReminders(userId); } async deleteCustomReminder(id: string): Promise { return this.strategy.deleteCustomReminder(id); } // User operations with password async createUserWithPassword( email: string, hashedPassword: string, username?: string ) { return this.strategy.createUserWithPassword( email, hashedPassword, username ); } async createUserFromOAuth(email: string, username: string, provider: string) { return this.strategy.createUserFromOAuth(email, username, provider); } // Utility methods getStrategyType(): string { return this.strategy.constructor.name; } isUsingMockStrategy(): boolean { return this.strategy instanceof MockDatabaseStrategy; } isUsingProductionStrategy(): boolean { return this.strategy instanceof ProductionDatabaseStrategy; } async suspendUser(userId: string) { const user = await this.strategy.getUserById(userId); if (!user) throw new Error('User not found'); return this.strategy.updateUser({ ...user, status: AccountStatus.SUSPENDED, }); } async activateUser(userId: string) { const user = await this.strategy.getUserById(userId); if (!user) throw new Error('User not found'); return this.strategy.updateUser({ ...user, status: AccountStatus.ACTIVE, }); } async changeUserPassword(userId: string, newPassword: string) { const user = await this.strategy.getUserById(userId); if (!user) throw new Error('User not found'); return this.strategy.updateUser({ ...user, password: newPassword, }); } async deleteAllUserData(userId: string) { // Delete user's medications const medications = await this.strategy.getMedications(userId); for (const med of medications) { await this.strategy.deleteMedication(med._id); } // Delete user's reminders const reminders = await this.strategy.getCustomReminders(userId); for (const reminder of reminders) { await this.strategy.deleteCustomReminder(reminder._id); } // Delete user return this.strategy.deleteUser(userId); } } // Export singleton instance export const databaseService = new DatabaseService(); // Re-export types and errors export { DatabaseError } from './types'; export type { DatabaseStrategy } from './types';