export default () => ({ nodeEnv: process.env.NODE_ENV ?? 'development', port: Number(process.env.PORT ?? 4000), host: process.env.HOST ?? '0.0.0.0', publicBaseUrl: process.env.PUBLIC_BASE_URL ?? `http://localhost:${Number(process.env.PORT ?? 4000)}`, responseEnvelopeEnabled: (process.env.RESPONSE_ENVELOPE_ENABLED ?? 'false').toLowerCase() === 'true', globalPrefix: process.env.GLOBAL_PREFIX ?? 'api/v1', cors: { origins: (process.env.CORS_ORIGINS ?? '') .split(',') .map((origin) => origin.trim()) .filter((origin) => origin.length > 0), }, mongodb: { uri: process.env.MONGODB_URI ?? 'mongodb://127.0.0.1:27017/oudelaa', }, jwt: { accessSecret: process.env.JWT_ACCESS_SECRET ?? '', accessExpiresIn: process.env.JWT_ACCESS_EXPIRES_IN ?? '15m', refreshSecret: process.env.JWT_REFRESH_SECRET ?? '', refreshExpiresIn: process.env.JWT_REFRESH_EXPIRES_IN ?? '30d', }, superAdmin: { email: (process.env.SUPERADMIN_EMAIL ?? '').toLowerCase(), password: process.env.SUPERADMIN_PASSWORD ?? '', accessSecret: process.env.SUPERADMIN_ACCESS_SECRET ?? '', accessExpiresIn: process.env.SUPERADMIN_ACCESS_EXPIRES_IN ?? '15m', refreshSecret: process.env.SUPERADMIN_REFRESH_SECRET ?? '', refreshExpiresIn: process.env.SUPERADMIN_REFRESH_EXPIRES_IN ?? '30d', }, google: { clientId: process.env.GOOGLE_CLIENT_ID ?? '', clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? '', callbackUrl: process.env.GOOGLE_CALLBACK_URL ?? 'http://localhost:4000/api/v1/auth/google/callback', }, email: { enabled: (process.env.EMAIL_ENABLED ?? 'false').toLowerCase() === 'true', smtpHost: process.env.EMAIL_SMTP_HOST ?? 'smtp.gmail.com', smtpPort: Number(process.env.EMAIL_SMTP_PORT ?? 587), smtpSecure: (process.env.EMAIL_SMTP_SECURE ?? 'false').toLowerCase() === 'true', smtpUser: process.env.EMAIL_SMTP_USER ?? '', smtpPass: process.env.EMAIL_SMTP_PASS ?? '', fromName: process.env.EMAIL_FROM_NAME ?? 'Oudelaa', fromEmail: process.env.EMAIL_FROM_EMAIL ?? process.env.EMAIL_SMTP_USER ?? '', }, aiMusic: { enabled: (process.env.AI_MUSIC_ENABLED ?? 'false').toLowerCase() === 'true', apiKey: process.env.AI_MUSIC_API_KEY ?? '', projectId: process.env.AI_MUSIC_PROJECT_ID ?? '', location: process.env.AI_MUSIC_LOCATION ?? 'us-central1', model: process.env.AI_MUSIC_MODEL ?? 'lyria-002', }, security: { bcryptSaltRounds: Number(process.env.BCRYPT_SALT_ROUNDS ?? 12), refreshTokenHashSecret: process.env.REFRESH_TOKEN_HASH_SECRET ?? process.env.JWT_REFRESH_SECRET ?? '', }, redis: { enabled: (process.env.REDIS_ENABLED ?? 'false').toLowerCase() === 'true', url: process.env.REDIS_URL ?? '', host: process.env.REDIS_HOST ?? '127.0.0.1', port: Number(process.env.REDIS_PORT ?? 6379), username: process.env.REDIS_USERNAME ?? '', password: process.env.REDIS_PASSWORD ?? '', db: Number(process.env.REDIS_DB ?? 0), keyPrefix: process.env.REDIS_KEY_PREFIX ?? 'oudelaa', socketAdapterEnabled: (process.env.REDIS_SOCKET_ADAPTER_ENABLED ?? 'false').toLowerCase() === 'true', }, queue: { enabled: (process.env.QUEUE_ENABLED ?? 'false').toLowerCase() === 'true', name: process.env.QUEUE_NAME ?? 'app-jobs', defaultJobAttempts: Number(process.env.QUEUE_DEFAULT_ATTEMPTS ?? 3), defaultJobBackoffMs: Number(process.env.QUEUE_DEFAULT_BACKOFF_MS ?? 1000), removeOnComplete: (process.env.QUEUE_REMOVE_ON_COMPLETE ?? 'true').toLowerCase() === 'true', workerConcurrency: Number(process.env.QUEUE_WORKER_CONCURRENCY ?? 5), }, storage: { provider: process.env.STORAGE_PROVIDER ?? 'local', basePath: process.env.STORAGE_BASE_PATH ?? 'uploads', publicBaseUrl: process.env.STORAGE_PUBLIC_BASE_URL ?? '', s3: { bucket: process.env.S3_BUCKET ?? '', region: process.env.S3_REGION ?? 'auto', endpoint: process.env.S3_ENDPOINT ?? '', accessKeyId: process.env.S3_ACCESS_KEY_ID ?? '', secretAccessKey: process.env.S3_SECRET_ACCESS_KEY ?? '', forcePathStyle: (process.env.S3_FORCE_PATH_STYLE ?? 'false').toLowerCase() === 'true', healthWriteTestEnabled: (process.env.S3_HEALTH_WRITE_TEST_ENABLED ?? 'false').toLowerCase() === 'true', }, }, imageProcessing: { enabled: typeof process.env.IMAGE_PROCESSING_ENABLED === 'string' ? process.env.IMAGE_PROCESSING_ENABLED.toLowerCase() === 'true' : (process.env.VIDEO_PROCESSING_ENABLED ?? 'false').toLowerCase() === 'true', ffmpegPath: process.env.IMAGE_PROCESSING_FFMPEG_PATH ?? process.env.VIDEO_PROCESSING_FFMPEG_PATH ?? 'ffmpeg', lowWidth: Number(process.env.IMAGE_PROCESSING_LOW_WIDTH ?? 360), mediumWidth: Number(process.env.IMAGE_PROCESSING_MEDIUM_WIDTH ?? 720), highWidth: Number(process.env.IMAGE_PROCESSING_HIGH_WIDTH ?? 1280), quality: Number(process.env.IMAGE_PROCESSING_QUALITY ?? 78), }, videoProcessing: { enabled: (process.env.VIDEO_PROCESSING_ENABLED ?? 'false').toLowerCase() === 'true', ffmpegPath: process.env.VIDEO_PROCESSING_FFMPEG_PATH ?? 'ffmpeg', ffprobePath: process.env.VIDEO_PROCESSING_FFPROBE_PATH ?? '', maxWidth: Number(process.env.VIDEO_PROCESSING_MAX_WIDTH ?? 1280), maxFps: Number(process.env.VIDEO_PROCESSING_MAX_FPS ?? 30), crf: Number(process.env.VIDEO_PROCESSING_CRF ?? 28), preset: process.env.VIDEO_PROCESSING_PRESET ?? 'veryfast', audioBitrateKbps: Number(process.env.VIDEO_PROCESSING_AUDIO_BITRATE_KBPS ?? 128), generateThumbnails: (process.env.VIDEO_PROCESSING_GENERATE_THUMBNAILS ?? 'true').toLowerCase() === 'true', generateHls: (process.env.VIDEO_PROCESSING_GENERATE_HLS ?? 'true').toLowerCase() === 'true', hlsSegmentDurationSeconds: Number( process.env.VIDEO_PROCESSING_HLS_SEGMENT_DURATION_SECONDS ?? 4, ), thumbnailWidth: Number(process.env.VIDEO_PROCESSING_THUMBNAIL_WIDTH ?? 720), }, audioProcessing: { enabled: (process.env.AUDIO_PROCESSING_ENABLED ?? 'false').toLowerCase() === 'true', waveformPeaks: Number(process.env.AUDIO_WAVEFORM_PEAKS ?? 48), }, logging: { level: process.env.LOG_LEVEL ?? 'log', requestEnabled: (process.env.REQUEST_LOGGING_ENABLED ?? 'true').toLowerCase() === 'true', }, feedCache: { enabled: (process.env.FEED_CACHE_ENABLED ?? 'true').toLowerCase() === 'true', userFeedTtlSeconds: Number(process.env.FEED_CACHE_USER_TTL_SECONDS ?? 15), trendingTtlSeconds: Number(process.env.FEED_CACHE_TRENDING_TTL_SECONDS ?? 30), }, performance: { feedTimingLogsEnabled: (process.env.FEED_TIMING_LOGS_ENABLED ?? 'false').toLowerCase() === 'true', }, passwordReset: { codeExpiresMinutes: Number(process.env.PASSWORD_RESET_CODE_EXPIRES_MINUTES ?? 10), maxAttempts: Number(process.env.PASSWORD_RESET_MAX_ATTEMPTS ?? 5), tokenSecret: process.env.PASSWORD_RESET_TOKEN_SECRET ?? process.env.JWT_ACCESS_SECRET ?? '', tokenExpiresIn: process.env.PASSWORD_RESET_TOKEN_EXPIRES_IN ?? '15m', }, emailVerification: { codeExpiresMinutes: Number(process.env.EMAIL_VERIFICATION_CODE_EXPIRES_MINUTES ?? 10), maxAttempts: Number(process.env.EMAIL_VERIFICATION_MAX_ATTEMPTS ?? 5), }, swagger: { title: process.env.SWAGGER_TITLE ?? 'Oudelaa API', description: process.env.SWAGGER_DESCRIPTION ?? 'Social media backend API documentation', version: process.env.SWAGGER_VERSION ?? '1.0.0', path: process.env.SWAGGER_PATH ?? 'docs', }, });