// ENVIRONMENT require('dotenv').config(); // DATABASE const { PrismaClient: CMSClient, ActivityType } = require("../../prisma/clients/cms"); const prisma = new CMSClient(); // RESPONSES const { badRequestResponse } = require("../res/responses.js"); const { successResponse } = require("../res/responses.js"); // SERVICES const { localTime } = require("../services/time.services.js"); const logger = require("../services/logger.services.js"); const { manualTriggerNotification, processActivitiesAndSendNotifications, analyzeUserActivitiesForNotification, updateDailyAnalytics, getAINotificationAnalytics } = require("../services/notification.services.js"); // CONTROLLER exports.create = async (req, res) => { try { const { userID, activityType, params } = req.body; if (!userID || !activityType || !params) { throw new Error("Invalid user ID, activity type, or params!"); } if (!Object.values(ActivityType).includes(activityType)) { throw new Error(`Invalid activity type value, allowed values: ${Object.values(ActivityType).join(", ")}`); } const userToken = await prisma.usersToken.findUnique({ where: { UserID_UT: userID } }); if (!userToken) { throw new Error(`User token not found for userID: ${userID}. Please register user token first.`); } let parsedParams = params; if (typeof params === 'string' && params.startsWith('{')) { try { parsedParams = params; } catch (e) { parsedParams = params; } } const activity = await prisma.usersActivity.create({ data: { UUID_UT: userToken.UUID_UT, ActivityType_UA: activityType, Params_UA: parsedParams, NotifyAt_UA: localTime(new Date(Date.now() + 1000 * 60 * 5)), CreatedAt_UA: localTime(new Date()), UpdatedAt_UA: localTime(new Date()) } }); return successResponse(res, "User activity created successfully!", { activityID: activity.UUID_UA, userID: userID, activityType: activity.ActivityType_UA, createdAt: activity.CreatedAt_UA, willTriggerAIAnalysis: true }); } catch (err) { return badRequestResponse(res, "Error creating user activity", err); } } exports.triggerNotificationForUser = async (req, res) => { try { const { userID, timeRangeMinutes = 60 } = req.body; if (!userID) { throw new Error("userID is required"); } const result = await manualTriggerNotification(userID, timeRangeMinutes); if (result.success) { return successResponse(res, "Notification sent successfully!", result); } else { return badRequestResponse(res, `Failed to send notification: ${result.reason || result.error}`, result); } } catch (err) { logger.error("Error triggering notification", { error: err.message, stack: err.stack }); return badRequestResponse(res, "Error triggering notification", err); } } exports.analyzeUserActivities = async (req, res) => { try { const { userID, timeRangeMinutes = 60 } = req.body; if (!userID) { throw new Error("userID is required"); } const analysis = await analyzeUserActivitiesForNotification(userID, timeRangeMinutes); return successResponse(res, "Activity analysis completed", analysis); } catch (err) { return badRequestResponse(res, "Error analyzing activities", err); } } exports.processAllActivitiesAndNotifications = async (req, res) => { try { const { timeRangeMinutes = 30, minActivityCount = 1 } = req.body; const result = await processActivitiesAndSendNotifications({ timeRangeMinutes, minActivityCount }); if (result.notificationsSent > 0) { try { await updateDailyAnalytics(); result.analyticsUpdated = true; } catch (analyticsErr) { result.analyticsUpdated = false; } } return successResponse(res, "Activity processing completed", { ...result, message: `Processed ${result.totalUsersProcessed} users, sent ${result.notificationsSent} AI notifications` }); } catch (err) { return badRequestResponse(res, "Error processing activities", err); } } exports.getAIInsights = async (req, res) => { try { const { userID, timeRange = 30 } = req.query; // Get AI notification analytics const analytics = await getAINotificationAnalytics({ startDate: new Date(Date.now() - timeRange * 24 * 60 * 60 * 1000), endDate: new Date(), limit: 50 }); let userSpecificData = null; if (userID) { // Get user-specific AI notifications userSpecificData = await prisma.aINotification.findMany({ where: { UserID_AIN: userID, CreatedAt_AIN: { gte: new Date(Date.now() - timeRange * 24 * 60 * 60 * 1000) } }, orderBy: { CreatedAt_AIN: 'desc' }, take: 10 }); // Get user's recent activities const userToken = await prisma.usersToken.findFirst({ where: { UserID_UT: userID } }); if (userToken) { userSpecificData = { notifications: userSpecificData, recentActivities: await prisma.usersActivity.findMany({ where: { UUID_UT: userToken.UUID_UT, CreatedAt_UA: { gte: new Date(Date.now() - 24 * 60 * 60 * 1000) // Last 24 hours } }, orderBy: { CreatedAt_UA: 'desc' }, take: 20 }) }; } } return successResponse(res, "AI insights retrieved successfully!", { analytics: analytics.summary, userSpecificData, integrationStatus: { aiNotificationsEnabled: true, analyticsTracking: true, activityMonitoring: true } }); } catch (err) { return badRequestResponse(res, "Error retrieving AI insights", err); } }