import Joi from '@hapi/joi'; import { EventCollector } from '../services/EventCollector.js'; import { MetricsProcessor } from '../services/MetricsProcessor.js'; import { RealtimeAnalytics } from '../services/RealtimeAnalytics.js'; import { ReportGenerator } from '../services/ReportGenerator.js'; import { AlertManager } from '../services/AlertManager.js'; import { logger } from '../utils/logger.js'; import dashboardRoutes from './dashboard.js'; const eventCollector = EventCollector.getInstance(); const metricsProcessor = MetricsProcessor.getInstance(); const realtimeAnalytics = RealtimeAnalytics.getInstance(); const reportGenerator = ReportGenerator.getInstance(); const alertManager = AlertManager.getInstance(); export default [ ...dashboardRoutes, // Event Collection Routes { method: 'POST', path: '/api/v1/events', options: { validate: { payload: Joi.object({ type: Joi.string().required(), accountId: Joi.string().required(), userId: Joi.string().optional(), sessionId: Joi.string().optional(), action: Joi.string().required(), target: Joi.string().optional(), value: Joi.number().optional(), metadata: Joi.object().optional(), properties: Joi.object().optional() }) }, handler: async (request, h) => { try { const result = await eventCollector.collectEvent(request.payload); return h.response({ success: true, data: result }); } catch (error) { logger.error('Event collection error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'POST', path: '/api/v1/events/bulk', options: { validate: { payload: Joi.object({ events: Joi.array().items( Joi.object({ type: Joi.string().required(), accountId: Joi.string().required(), userId: Joi.string().optional(), sessionId: Joi.string().optional(), action: Joi.string().required(), target: Joi.string().optional(), value: Joi.number().optional(), metadata: Joi.object().optional(), properties: Joi.object().optional() }) ).required() }) }, handler: async (request, h) => { try { const { events } = request.payload; const result = await eventCollector.collectBulkEvents(events); return h.response({ success: true, data: result }); } catch (error) { logger.error('Bulk event collection error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'GET', path: '/api/v1/events', options: { validate: { query: Joi.object({ type: Joi.string().optional(), accountId: Joi.string().optional(), userId: Joi.string().optional(), startTime: Joi.date().iso().optional(), endTime: Joi.date().iso().optional(), limit: Joi.number().min(1).max(1000).default(100), offset: Joi.number().min(0).default(0), aggregation: Joi.string().valid('hourly', 'daily', 'by_type').optional() }) }, handler: async (request, h) => { try { const result = await eventCollector.queryEvents(request.query); return h.response({ success: true, data: result }); } catch (error) { logger.error('Event query error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, // Metrics Routes { method: 'GET', path: '/api/v1/metrics/{metricId}', options: { validate: { params: Joi.object({ metricId: Joi.string().required() }), query: Joi.object({ startTime: Joi.date().iso().optional(), endTime: Joi.date().iso().optional(), dimensions: Joi.object().optional(), limit: Joi.number().min(1).max(10000).default(1000) }) }, handler: async (request, h) => { try { const { metricId } = request.params; const result = await metricsProcessor.getMetric(metricId, request.query); return h.response({ success: true, data: result }); } catch (error) { logger.error('Metric query error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'GET', path: '/api/v1/metrics/{metricId}/summary', options: { validate: { params: Joi.object({ metricId: Joi.string().required() }) }, handler: async (request, h) => { try { const { metricId } = request.params; const result = await metricsProcessor.getMetricSummary(metricId); return h.response({ success: true, data: result }); } catch (error) { logger.error('Metric summary error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'PUT', path: '/api/v1/metrics/{metricId}', options: { validate: { params: Joi.object({ metricId: Joi.string().required() }), payload: Joi.object({ name: Joi.string(), description: Joi.string(), formula: Joi.string(), dimensions: Joi.array().items(Joi.string()), aggregations: Joi.array().items(Joi.string()), refreshInterval: Joi.number(), retentionDays: Joi.number(), active: Joi.boolean() }) }, handler: async (request, h) => { try { const { metricId } = request.params; const result = await metricsProcessor.updateMetricDefinition(metricId, request.payload); return h.response({ success: true, data: result }); } catch (error) { logger.error('Metric update error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, // Real-time Analytics Routes { method: 'GET', path: '/api/v1/realtime/dashboard/{accountId}', options: { validate: { params: Joi.object({ accountId: Joi.string().required() }) }, handler: async (request, h) => { try { const { accountId } = request.params; const result = await realtimeAnalytics.getDashboard(accountId); return h.response({ success: true, data: result }); } catch (error) { logger.error('Dashboard error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'POST', path: '/api/v1/realtime/subscribe', options: { validate: { payload: Joi.object({ accountId: Joi.string().required(), metrics: Joi.array().items(Joi.string()).required(), filters: Joi.object().optional() }) }, handler: async (request, h) => { try { const { accountId, metrics, filters } = request.payload; const subscriptionId = await realtimeAnalytics.subscribe(accountId, metrics, filters); return h.response({ success: true, data: { subscriptionId } }); } catch (error) { logger.error('Subscription error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'DELETE', path: '/api/v1/realtime/subscribe/{subscriptionId}', options: { validate: { params: Joi.object({ subscriptionId: Joi.string().required() }) }, handler: async (request, h) => { try { const { subscriptionId } = request.params; const result = realtimeAnalytics.unsubscribe(subscriptionId); return h.response({ success: true, data: { unsubscribed: result } }); } catch (error) { logger.error('Unsubscribe error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, // Report Generation Routes { method: 'POST', path: '/api/v1/reports/generate', options: { validate: { payload: Joi.object({ accountId: Joi.string().required(), type: Joi.string().valid( 'campaign_performance', 'user_analytics', 'ab_test' ).required(), period: Joi.string().valid( 'today', 'yesterday', 'this_week', 'last_week', 'this_month', 'last_month', 'last_30_days', 'last_90_days' ).optional(), startDate: Joi.date().iso().optional(), endDate: Joi.date().iso().optional(), filters: Joi.object().optional(), format: Joi.string().valid('json', 'pdf', 'excel', 'csv').default('json') }) }, handler: async (request, h) => { try { const result = await reportGenerator.generateReport(request.payload); return h.response({ success: true, data: result }); } catch (error) { logger.error('Report generation error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'POST', path: '/api/v1/reports/schedule', options: { validate: { payload: Joi.object({ accountId: Joi.string().required(), type: Joi.string().required(), schedule: Joi.string().required(), // cron expression recipients: Joi.array().items(Joi.string()).required(), format: Joi.string().valid('pdf', 'excel', 'csv').default('pdf') }) }, handler: async (request, h) => { try { const result = await reportGenerator.scheduleReport(request.payload); return h.response({ success: true, data: result }); } catch (error) { logger.error('Report scheduling error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'GET', path: '/api/v1/reports/history', options: { validate: { query: Joi.object({ accountId: Joi.string().required(), limit: Joi.number().min(1).max(100).default(20) }) }, handler: async (request, h) => { try { const { accountId, limit } = request.query; const result = await reportGenerator.getReportHistory(accountId, limit); return h.response({ success: true, data: result }); } catch (error) { logger.error('Report history error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, // Alert Management Routes { method: 'POST', path: '/api/v1/alerts/rules', options: { validate: { payload: Joi.object({ ruleId: Joi.string().required(), name: Joi.string().required(), description: Joi.string().optional(), metric: Joi.string().required(), condition: Joi.object({ operator: Joi.string().valid('>', '>=', '<', '<=', '=', '==', '!=').required(), threshold: Joi.number().required(), duration: Joi.number().min(0).default(300) }).required(), severity: Joi.string().valid('low', 'medium', 'high', 'critical').required(), channels: Joi.array().items(Joi.string()).required(), cooldown: Joi.number().min(0).default(1800), accountId: Joi.string().optional(), active: Joi.boolean().default(true) }) }, handler: async (request, h) => { try { const result = await alertManager.createAlertRule(request.payload); return h.response({ success: true, data: result }); } catch (error) { logger.error('Alert rule creation error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'PUT', path: '/api/v1/alerts/rules/{ruleId}', options: { validate: { params: Joi.object({ ruleId: Joi.string().required() }), payload: Joi.object({ name: Joi.string(), description: Joi.string(), condition: Joi.object(), severity: Joi.string().valid('low', 'medium', 'high', 'critical'), channels: Joi.array().items(Joi.string()), cooldown: Joi.number(), active: Joi.boolean() }) }, handler: async (request, h) => { try { const { ruleId } = request.params; const result = await alertManager.updateAlertRule(ruleId, request.payload); return h.response({ success: true, data: result }); } catch (error) { logger.error('Alert rule update error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'DELETE', path: '/api/v1/alerts/rules/{ruleId}', options: { validate: { params: Joi.object({ ruleId: Joi.string().required() }) }, handler: async (request, h) => { try { const { ruleId } = request.params; const result = await alertManager.deleteAlertRule(ruleId); return h.response({ success: true, data: result }); } catch (error) { logger.error('Alert rule deletion error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'GET', path: '/api/v1/alerts/history', options: { validate: { query: Joi.object({ ruleId: Joi.string().optional(), severity: Joi.string().optional(), startTime: Joi.date().iso().optional(), endTime: Joi.date().iso().optional(), limit: Joi.number().min(1).max(1000).default(100) }) }, handler: async (request, h) => { try { const result = await alertManager.getAlertHistory(request.query); return h.response({ success: true, data: result }); } catch (error) { logger.error('Alert history error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'POST', path: '/api/v1/alerts/{alertId}/acknowledge', options: { validate: { params: Joi.object({ alertId: Joi.string().required() }) }, handler: async (request, h) => { try { const { alertId } = request.params; const result = await alertManager.acknowledgeAlert(alertId); return h.response({ success: true, data: result }); } catch (error) { logger.error('Alert acknowledge error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'POST', path: '/api/v1/alerts/{alertId}/resolve', options: { validate: { params: Joi.object({ alertId: Joi.string().required() }), payload: Joi.object({ resolution: Joi.string().required() }) }, handler: async (request, h) => { try { const { alertId } = request.params; const { resolution } = request.payload; const result = await alertManager.resolveAlert(alertId, resolution); return h.response({ success: true, data: result }); } catch (error) { logger.error('Alert resolve error:', error); return h.response({ success: false, error: error.message }).code(500); } } } }, { method: 'GET', path: '/api/v1/alerts/stats', options: { validate: { query: Joi.object({ period: Joi.string().valid('1h', '24h', '7d').default('24h') }) }, handler: async (request, h) => { try { const { period } = request.query; const result = await alertManager.getAlertStats(period); return h.response({ success: true, data: result }); } catch (error) { logger.error('Alert stats error:', error); return h.response({ success: false, error: error.message }).code(500); } } } } ];