hye can you fix the bugg for 30s and 10s it is not logging nad o=some other bigs are happening make it best and wokring oin every. case and edgecase make it best and working perfect for everything 
"""
// services/monitorService.js

const axios = require('axios');
const cron = require('node-cron');
const Log = require('../models/Log');
const User = require('../models/User'); // Required for initialization
const screenshotService = require('./screenshotService');
const emailService = require('./emailService');
const logger = require('../utils/logger');

/**
 * Helper: Convert time period to cron expression
 * Returns null for intervals that require setInterval (e.g., '10s' and '30s')
 */
const timePeriodToCron = (timePeriod) => {
    switch (timePeriod) {
        case '10s':
        case '30s':
            return null; // Use setInterval instead of cron for these intervals
        case '1m':
            return '*/1 * * * *';
        case '3m':
            return '*/3 * * * *';
        case '5m':
            return '*/5 * * * *';
        case '10m':
            return '*/10 * * * *';
        case '1h':
            return '0 * * * *';
        default:
            return '*/1 * * * *'; // Default to every minute
    }
};

/**
 * In-memory storage for active cron jobs and intervals
 * Key: User ID (String)
 * Value: cron.Job instance or setInterval ID
 */
const userJobs = new Map();
const userIntervals = new Map();

/**
 * In-memory storage for notification timers
 * Prevents sending duplicate notifications within a certain timeframe
 * Structure: { userId: { url: timeoutObject } }
 */
const notificationTimers = new Map();

/**
 * Performs health checks on all URLs for a given user
 *
 * @param {Object} user - User object containing monitoring details
 */
const performChecks = async (user) => {
    for (const url of user.listOfUrls) {
        let startTime, endTime, responseTime;
        try {
            startTime = Date.now();
            const response = await axios.get(url, { timeout: 10000 });
            endTime = Date.now();
            responseTime = endTime - startTime;

            const statusCode = response.status;

            // Log successful check with response time
            await logStatus(user._id, url, statusCode, "None", responseTime);

            if (statusCode < 200 || statusCode >= 300) {
                // Handle non-2xx status codes
                await handleFailure(user, url, statusCode);
            } else {
                // Clear any existing notification timer on success
                clearNotificationTimer(user._id.toString(), url);
            }
        } catch (error) {
            endTime = Date.now();
            responseTime = endTime - startTime;

            let statusCode = error.response ? error.response.status : 0;
            let screenshotUrl = 'None';

            try {
                screenshotUrl = await screenshotService.takeScreenshot(url);
                logger.info(`Screenshot captured for ${url}`);
            } catch (screenshotError) {
                logger.error(`Failed to take screenshot for ${url}: ${screenshotError.message}`);
            }

            // Log failed check with response time and screenshot
            await logStatus(user._id, url, statusCode, screenshotUrl, responseTime);

            if (!isNotificationPending(user._id.toString(), url)) {
                await emailService.sendErrorNotification(user.email, url, statusCode, screenshotUrl);
                setNotificationTimer(user._id.toString(), url, 10 * 60 * 1000); // 10 minutes
            }
        }
    }
};

/**
 * Handles failures by sending notifications and setting notification timers
 *
 * @param {Object} user - User object
 * @param {string} url - URL that failed the check
 * @param {number} statusCode - HTTP status code received
 */
const handleFailure = async (user, url, statusCode) => {
    logger.warn(`URL check failed for ${url} with status code ${statusCode}`);

    if (isNotificationPending(user._id.toString(), url)) {
        logger.info(`Notification already pending for ${url}. Skipping email.`);
        return;
    }

    try {
        const screenshotUrl = await screenshotService.takeScreenshot(url);
        await emailService.sendErrorNotification(user.email, url, statusCode, screenshotUrl);
        await logStatus(user._id, url, statusCode, screenshotUrl);
    } catch (error) {
        logger.error(`Failed to handle failure for ${url}: ${error.message}`);
    }

    setNotificationTimer(user._id.toString(), url, 10 * 60 * 1000); // 10 minutes
};

/**
 * Logs the status of a URL check to the database
 *
 * @param {ObjectId} userId - ID of the user
 * @param {string} url - URL that was checked
 * @param {number} statusCode - HTTP status code received
 * @param {string} screenshotUrl - URL of the screenshot (if any)
 * @param {number} responseTime - Response time in milliseconds
 */
const logStatus = async (userId, url, statusCode, screenshotUrl, responseTime = 0) => {
    try {
        const log = new Log({
            user: userId,
            url,
            statusCode,
            screenshotUrl,
            checkedAt: new Date(),
            responseTime,
        });
        await log.save();
        logger.info(`Logged status for ${url} with status code ${statusCode}, response time: ${responseTime}ms, and screenshot URL: ${screenshotUrl}`);
    } catch (logError) {
        logger.error(`Failed to log status for ${url}: ${logError.message}`);
    }
};

/**
 * Starts monitoring for a user based on their settings
 *
 * @param {Object} user - User object containing monitoring details
 */
const startMonitoring = (user) => {
    if (!user.verified) {
        logger.warn(`Attempted to start monitoring for unverified user: ${user.username}`);
        throw new Error('Email not verified. Please verify your email before starting monitoring.');
    }

    if (!user.listOfUrls || user.listOfUrls.length === 0) {
        logger.warn(`No URLs to monitor for user: ${user.username}`);
        return;
    }

    // Prevent duplicate monitoring by stopping existing jobs or intervals
    stopMonitoring(user);

    const cronExpression = timePeriodToCron(user.timePeriod);

    if (cronExpression) {
        // Schedule using node-cron for minute-based or longer intervals
        const job = cron.schedule(cronExpression, () => {
            performChecks(user);
        }, {
            scheduled: true,
            timezone: "UTC",
        });

        userJobs.set(user._id.toString(), job);
        logger.info(`Started cron job (${cronExpression}) monitoring for user ${user.username}`);
    } else if (user.timePeriod === '10s' || user.timePeriod === '30s') {
        // Use setInterval for second-based intervals
        const intervalMs = user.timePeriod === '10s' ? 10 * 1000 : 30 * 1000;
        const interval = setInterval(() => {
            performChecks(user);
        }, intervalMs);

        userIntervals.set(user._id.toString(), interval);
        logger.info(`Started ${user.timePeriod} interval monitoring for user ${user.username}`);
    } else {
        logger.warn(`Unsupported time period "${user.timePeriod}" for user ${user.username}. Defaulting to every minute.`);
        // Defaulting to every minute if unsupported timePeriod is provided
        const defaultCron = '*/1 * * * *';
        const job = cron.schedule(() => {
            performChecks(user);
        }, defaultCron, {
            scheduled: true,
            timezone: "UTC",
        });

        userJobs.set(user._id.toString(), job);
        logger.info(`Started default cron job (${defaultCron}) monitoring for user ${user.username}`);
    }
};

/**
 * Stops monitoring for a user by clearing their cron job or interval
 *
 * @param {Object} user - User object
 */
const stopMonitoring = (user) => {
    const userId = user._id.toString();

    if (userJobs.has(userId)) {
        const job = userJobs.get(userId);
        job.stop();
        userJobs.delete(userId);
        logger.info(`Stopped cron job monitoring for user ${user.username}`);
    }

    if (userIntervals.has(userId)) {
        clearInterval(userIntervals.get(userId));
        userIntervals.delete(userId);
        logger.info(`Stopped interval monitoring for user ${user.username}`);
    }

    // Clear any pending notification timers
    if (notificationTimers.has(userId)) {
        const userTimers = notificationTimers.get(userId);
        for (const url in userTimers) {
            clearTimeout(userTimers[url]);
            logger.info(`Cleared notification timer for ${url} (User: ${user.username})`);
        }
        notificationTimers.delete(userId);
    }
};

/**
 * Restarts monitoring for a user by stopping existing monitoring and starting anew
 *
 * @param {Object} user - User object
 */
const restartMonitoring = (user) => {
    if (!user.verified) {
        logger.warn(`Attempted to restart monitoring for unverified user: ${user.username}`);
        throw new Error('Email not verified. Please verify your email before restarting monitoring.');
    }
    stopMonitoring(user);
    startMonitoring(user);
};

/**
 * Checks if monitoring is active for a given user
 *
 * @param {string} userId - ID of the user
 * @returns {boolean} - True if monitoring is active, else false
 */
const isMonitoringActive = (userId) => {
    return userJobs.has(userId) || userIntervals.has(userId);
};

/**
 * Checks if a notification is pending for a specific user's URL
 *
 * @param {string} userId - ID of the user
 * @param {string} url - URL being monitored
 * @returns {boolean} - True if notification is pending, else false
 */
const isNotificationPending = (userId, url) => {
    if (!notificationTimers.has(userId)) return false;
    const userTimers = notificationTimers.get(userId);
    return Object.prototype.hasOwnProperty.call(userTimers, url);
};

/**
 * Sets a notification timer to prevent duplicate notifications
 *
 * @param {string} userId - ID of the user
 * @param {string} url - URL being monitored
 * @param {number} timeout - Duration to wait before allowing another notification (in ms)
 */
const setNotificationTimer = (userId, url, timeout) => {
    if (!notificationTimers.has(userId)) {
        notificationTimers.set(userId, {});
    }
    const userTimers = notificationTimers.get(userId);
    userTimers[url] = setTimeout(() => {
        // Timer expired, remove the pending notification
        if (notificationTimers.has(userId)) {
            delete userTimers[url];
            logger.info(`Notification timer expired for ${url} (User ID: ${userId})`);
        }
    }, timeout);
};

/**
 * Clears a notification timer when a URL recovers
 *
 * @param {string} userId - ID of the user
 * @param {string} url - URL being monitored
 */
const clearNotificationTimer = (userId, url) => {
    if (!notificationTimers.has(userId)) return;
    const userTimers = notificationTimers.get(userId);
    if (userTimers[url]) {
        clearTimeout(userTimers[url]);
        delete userTimers[url];
        logger.info(`Cleared notification timer for ${url} (User ID: ${userId})`);
    }
};

/**
 * Initializes monitoring for all existing verified users
 * Should be called once when the server starts
 */
const initializeMonitoring = async () => {
    try {
        const users = await User.find({ verified: true });
        users.forEach(user => {
            startMonitoring(user);
        });
        logger.info('Initialized monitoring for all existing verified users.');
    } catch (error) {
        logger.error('Error initializing monitoring:', error);
    }
};

/**
 * Stops all active monitoring (used during graceful shutdown)
 */
const stopAllMonitoring = () => {
    // Stop all cron jobs
    for (const [userId, job] of userJobs.entries()) {
        job.stop();
        logger.info(`Stopped cron job for user ID: ${userId}`);
    }
    userJobs.clear();

    // Stop all intervals
    for (const [userId, interval] of userIntervals.entries()) {
        clearInterval(interval);
        logger.info(`Stopped interval monitoring for user ID: ${userId}`);
    }
    userIntervals.clear();

    // Clear all notification timers
    for (const [userId, timers] of notificationTimers.entries()) {
        for (const url in timers) {
            clearTimeout(timers[url]);
            logger.info(`Cleared notification timer for ${url} (User ID: ${userId})`);
        }
    }
    notificationTimers.clear();

    logger.info('All monitoring and notification timers have been stopped.');
};

/**
 * Gracefully stops all monitoring and cleans up resources
 * Should be called during server shutdown
 */
const gracefulShutdown = () => {
    logger.info('Initiating graceful shutdown...');
    stopAllMonitoring();
    // Additional shutdown tasks can be added here
    // e.g., closing database connections, flushing logs, etc.
};

module.exports = {
    startMonitoring,
    stopMonitoring,
    restartMonitoring,
    initializeMonitoring,
    isMonitoringActive,
    stopAllMonitoring,
    gracefulShutdown, // Exported for server shutdown handling
};
"""
"""
const { z } = require('zod');
const mongoose = require('mongoose');
const User = require('../models/User');
const Log = require('../models/Log');
const monitorService = require('../services/monitorService');
const logger = require('../utils/logger');

/**
 * Zod Schemas for Validation
 */

/**
 * Schema for updating user settings
 * Allows updating the list of URLs, monitoring time period, and email notifications.
 */
const updateSettingsSchema = z.object({
    listOfUrls: z.array(z.string().url()).optional(),
    timePeriod: z.enum(['30s', '1m', '3m', '5m', '10m', '1h']).optional(),
    emailSend: z.boolean().optional(),
});

/**
 * Schema for getting user logs with pagination
 * Validates the `page` and `limit` query parameters.
 */
const getLogsQuerySchema = z.object({
    page: z
        .string()
        .optional()
        .refine((val) => !val || /^\d+$/.test(val), {
            message: 'page must be a positive integer',
        })
        .default('1'),
    limit: z
        .string()
        .optional()
        .refine((val) => !val || (/^\d+$/.test(val) && parseInt(val) <= 1000), {
            message: 'limit must be a positive integer not exceeding 1000',
        })
        .default('20'),
});

/**
 * Zod schema for analytics parameters
 * Validates various query parameters for generating analytics reports.
 */
const analyticsSchema = z.object({
    startDate: z.string().optional().refine((date) => !date || !isNaN(Date.parse(date)), {
        message: 'startDate must be a valid ISO date string',
    }),
    endDate: z.string().optional().refine((date) => !date || !isNaN(Date.parse(date)), {
        message: 'endDate must be a valid ISO date string',
    }),
    urls: z.string().optional().refine((urls) => !urls || urls.split(',').every((url) => {
        try { new URL(url.trim()); return true; } catch { return false; }
    }), { message: 'urls must be a comma-separated list of valid URLs' }),
    statusCodes: z.string().optional().refine((codes) => !codes || codes.split(',').every(code => /^\d+$/.test(code.trim())), {
        message: 'statusCodes must be a comma-separated list of numbers',
    }),
    minResponseTime: z.string().optional().refine(rt => !rt || /^\d+$/.test(rt), {
        message: 'minResponseTime must be a number representing milliseconds',
    }),
    maxResponseTime: z.string().optional().refine(rt => !rt || /^\d+$/.test(rt), {
        message: 'maxResponseTime must be a number representing milliseconds',
    }),
    groupBy: z.enum(['hour', 'day', 'week', 'month']).optional().default('day'),
    page: z.string().optional().refine((val) => !val || /^\d+$/.test(val), {
        message: 'page must be a positive integer',
    }).default('1'),
    limit: z.string().optional().refine((val) => !val || (/^\d+$/.test(val) && parseInt(val) <= 1000), {
        message: 'limit must be an integer between 1 and 1000',
    }).default('100'),
});

/**
 * Controller Methods
 */

/**
 * Update User Settings
 * Route: PATCH /api/user/settings
 *
 * Allows users to update their monitoring settings, including the list of URLs, monitoring interval, and email notifications.
 */
exports.updateSettings = async (req, res) => {
    try {
        // Validate input data against the schema
        const parsedData = updateSettingsSchema.parse(req.body);

        // Update the user's settings in the database
        const updatedUser = await User.findByIdAndUpdate(
            req.user.id,
            { $set: parsedData },
            { new: true, runValidators: true, context: 'query' }
        );

        if (!updatedUser) {
            return res.status(404).json({ message: 'User not found' });
        }

        // If the user is verified, restart the monitoring service with the new settings
        if (updatedUser.verified) {
            try {
                monitorService.restartMonitoring(updatedUser);
            } catch (monitorError) {
                // Log the error and send a response if restarting monitoring fails
                logger.error('Restart Monitoring Error:', monitorError);
                return res.status(400).json({ message: monitorError.message });
            }
        } else {
            // If the user is not verified, log a warning and inform the user
            logger.warn(`User ${updatedUser.username} is not verified. Monitoring not started.`);
            return res.status(403).json({ message: 'Email not verified. Please verify your email to start monitoring.' });
        }

        // Send a success response with the updated user data
        res.status(200).json({ message: 'Settings updated successfully', user: updatedUser });
    } catch (error) {
        if (error instanceof z.ZodError) {
            // If validation fails, send a 400 response with error details
            return res.status(400).json({ errors: error.errors });
        }
        // Handle duplicate key errors (e.g., unique email or username constraints)
        if (error.code === 11000) {
            const field = Object.keys(error.keyValue)[0];
            return res.status(400).json({ message: `${field.charAt(0).toUpperCase() + field.slice(1)} already exists` });
        }
        // Log unexpected errors and send a 500 response
        logger.error('Update Settings Error:', error);
        res.status(500).json({ message: 'Server Error' });
    }
};

/**
 * Get User Logs
 * Route: GET /api/user/logs
 *
 * Retrieves the user's monitoring logs with pagination support.
 */
exports.getUserLogs = async (req, res) => {
    try {
        // Validate query parameters against the schema
        const parsedQuery = getLogsQuerySchema.parse(req.query);
        const page = parseInt(parsedQuery.page, 10);
        const limit = parseInt(parsedQuery.limit, 10);
        const skip = (page - 1) * limit;

        // Fetch logs from the database, sorted by the most recent
        const logs = await Log.find({ user: req.user.id })
                              .sort({ checkedAt: -1 })
                              .limit(limit)
                              .skip(skip)
                              .exec();

        // Get total count of logs for pagination
        const totalLogs = await Log.countDocuments({ user: req.user.id });

        // Send the logs along with pagination details
        res.status(200).json({
            totalPages: Math.ceil(totalLogs / limit),
            currentPage: page,
            logs,
        });
    } catch (error) {
        if (error instanceof z.ZodError) {
            // If validation fails, send a 400 response with error details
            return res.status(400).json({ errors: error.errors });
        }
        // Log unexpected errors and send a 500 response
        logger.error('Get User Logs Error:', error);
        res.status(500).json({ message: 'Server Error' });
    }
};

/**
 * Start Monitoring
 * Route: POST /api/user/monitor/start
 *
 * Initiates the monitoring service for the user based on their settings.
 */
exports.startMonitoring = async (req, res) => {
    try {
        const user = await User.findById(req.user.id);

        if (!user) {
            return res.status(404).json({ message: 'User not found' });
        }

        if (!user.verified) {
            return res.status(403).json({ message: 'Email not verified. Please verify your email to start monitoring.' });
        }

        if (!user.listOfUrls || user.listOfUrls.length === 0) {
            return res.status(400).json({ message: 'No URLs configured for monitoring. Please add URLs to your settings.' });
        }

        // Check if monitoring is already active for the user
        const isMonitoringActive = monitorService.isMonitoringActive(user._id.toString());
        if (isMonitoringActive) {
            return res.status(400).json({ message: 'Monitoring is already active for your account.' });
        }

        // Start monitoring using the monitorService
        monitorService.startMonitoring(user);

        // Send a success response
        res.status(200).json({ message: 'Monitoring started successfully.' });
    } catch (error) {
        // Log unexpected errors and send a 500 response
        logger.error('Start Monitoring Error:', error);
        res.status(500).json({ message: 'Internal server error' });
    }
};

/**
 * Stop Monitoring
 * Route: POST /api/user/monitor/stop
 *
 * Stops the monitoring service for the user.
 */
exports.stopMonitoring = async (req, res) => {
    try {
        const user = await User.findById(req.user.id);

        if (!user) {
            return res.status(404).json({ message: 'User not found' });
        }

        // Check if monitoring is active for the user
        const isMonitoringActive = monitorService.isMonitoringActive(user._id.toString());
        if (!isMonitoringActive) {
            return res.status(400).json({ message: 'Monitoring is not active for your account.' });
        }

        // Stop monitoring using the monitorService
        monitorService.stopMonitoring(user);

        // Send a success response
        res.status(200).json({ message: 'Monitoring stopped successfully.' });
    } catch (error) {
        // Log unexpected errors and send a 500 response
        logger.error('Stop Monitoring Error:', error);
        res.status(500).json({ message: 'Internal server error' });
    }
};

/**
 * Get Analytics
 * Route: GET /api/user/analytics
 *
 * Retrieves analytics data for the user's monitored URLs.
 */
exports.getAnalytics = async (req, res) => {
    try {
        const userId = req.user.id;

        // Validate and parse query parameters
        const parsed = analyticsSchema.parse(req.query);
        const { startDate, endDate, urls, statusCodes, minResponseTime, maxResponseTime, groupBy, page, limit } = parsed;

        // Build the match criteria for MongoDB aggregation
        const matchCriteria = { user: new mongoose.Types.ObjectId(userId) };

        if (startDate || endDate) {
            matchCriteria.checkedAt = {};
            if (startDate) {
                matchCriteria.checkedAt.$gte = new Date(startDate);
            }
            if (endDate) {
                matchCriteria.checkedAt.$lte = new Date(endDate);
            }
        }

        if (urls) {
            const urlsArray = urls.split(',').map(url => url.trim());
            matchCriteria.url = { $in: urlsArray };
        }

        if (statusCodes) {
            const statusCodesArray = statusCodes.split(',').map(code => parseInt(code.trim()));
            matchCriteria.statusCode = { $in: statusCodesArray };
        }

        if (minResponseTime || maxResponseTime) {
            matchCriteria.responseTime = {};
            if (minResponseTime) {
                matchCriteria.responseTime.$gte = parseInt(minResponseTime, 10);
            }
            if (maxResponseTime) {
                matchCriteria.responseTime.$lte = parseInt(maxResponseTime, 10);
            }
        }

        /**
         * Aggregation Pipelines
         */

        // Total Checks
        const totalChecksPromise = Log.countDocuments(matchCriteria).exec();

        // Successful Checks (2xx)
        const successfulChecksPromise = Log.countDocuments({
            ...matchCriteria,
            statusCode: { $gte: 200, $lt: 300 },
        }).exec();

        // Failed Checks (4xx and 5xx)
        const failedChecksPromise = Log.countDocuments({
            ...matchCriteria,
            statusCode: { $gte: 400 },
        }).exec();

        // Status Code Distribution
        const statusCodeDistributionPromise = Log.aggregate([
            { $match: matchCriteria },
            {
                $group: {
                    _id: '$statusCode',
                    count: { $sum: 1 },
                },
            },
            { $sort: { count: -1 } },
        ]).exec();

        // Uptime Percentage per URL
        const uptimePerUrlPromise = Log.aggregate([
            { $match: { ...matchCriteria, statusCode: { $gte: 200, $lt: 300 } } },
            {
                $group: {
                    _id: '$url',
                    successCount: { $sum: 1 },
                },
            },
            {
                $lookup: {
                    from: 'logs',
                    let: { url: '$_id' },
                    pipeline: [
                        { $match: { 
                            $expr: { $eq: ['$url', '$$url'] },
                            ...(startDate || endDate ? {
                                ...(startDate ? { $gte: ['$checkedAt', new Date(startDate)] } : {}),
                                ...(endDate ? { $lte: ['$checkedAt', new Date(endDate)] } : {}),
                            } : {})
                        } },
                        { $count: 'totalCount' },
                    ],
                    as: 'total',
                },
            },
            {
                $addFields: {
                    totalCount: { $ifNull: [{ $arrayElemAt: ['$total.totalCount', 0] }, 0] },
                },
            },
            {
                $project: {
                    _id: 1,
                    successCount: 1,
                    totalCount: 1,
                    uptimePercentage: {
                        $cond: [
                            { $eq: ['$totalCount', 0] },
                            0,
                            { $multiply: [{ $divide: ['$successCount', '$totalCount'] }, 100] },
                        ],
                    },
                },
            },
        ]).exec();

        // Checks Over Time with Average Response Time
        const checksOverTimePromise = Log.aggregate([
            { $match: matchCriteria },
            {
                $group: {
                    _id: {
                        year: { $year: '$checkedAt' },
                        month: { $month: '$checkedAt' },
                        week: { $week: '$checkedAt' },
                        day: { $dayOfMonth: '$checkedAt' },
                        hour: { $hour: '$checkedAt' },
                    },
                    count: { $sum: 1 },
                    averageResponseTime: { $avg: '$responseTime' },
                },
            },
            {
                $project: {
                    _id: 0,
                    period: getPeriodExpression(groupBy),
                    count: 1,
                    averageResponseTime: 1,
                },
            },
            {
                $group: {
                    _id: '$period',
                    total: { $sum: '$count' },
                    averageResponseTime: { $avg: '$averageResponseTime' },
                },
            },
            { $sort: { '_id': 1 } },
        ]).exec();

        // Response Time Distribution
        const responseTimeDistributionPromise = Log.aggregate([
            { $match: matchCriteria },
            {
                $bucket: {
                    groupBy: '$responseTime',
                    boundaries: [0, 100, 300, 500, 1000, 3000, 5000, Infinity],
                    default: '5000+',
                    output: {
                        count: { $sum: 1 },
                        averageResponseTime: { $avg: '$responseTime' },
                    },
                },
            },
            { $sort: { _id: 1 } },
        ]).exec();

        // Top Slowest URLs
        const topSlowestUrlsPromise = Log.aggregate([
            { $match: matchCriteria },
            {
                $group: {
                    _id: '$url',
                    averageResponseTime: { $avg: '$responseTime' },
                    totalChecks: { $sum: 1 },
                },
            },
            { $sort: { averageResponseTime: -1 } },
            { $limit: 10 },
        ]).exec();

        // Recent Issues
        const recentIssuesPromise = Log.find({
            ...matchCriteria,
            statusCode: { $gte: 400 }, // Client and Server errors
        })
            .sort({ checkedAt: -1 })
            .limit(10)
            .select('url statusCode checkedAt screenshotUrl responseTime')
            .exec();

        // Execute all aggregation promises concurrently
        const [
            totalChecks,
            successfulChecks,
            failedChecks,
            statusCodeDistribution,
            uptimePerUrl,
            checksOverTime,
            responseTimeDistribution,
            topSlowestUrls,
            recentIssues,
        ] = await Promise.all([
            totalChecksPromise,
            successfulChecksPromise,
            failedChecksPromise,
            statusCodeDistributionPromise,
            uptimePerUrlPromise,
            checksOverTimePromise,
            responseTimeDistributionPromise,
            topSlowestUrlsPromise,
            recentIssuesPromise,
        ]);

        // Calculate success and failure percentages with safe defaults
        const successPercentage = totalChecks > 0 ? (((successfulChecks / totalChecks) * 100) || 0).toFixed(2) : '0.00';
        const failurePercentage = totalChecks > 0 ? (((failedChecks / totalChecks) * 100) || 0).toFixed(2) : '0.00';

        // Structure the analytics response
        const analytics = {
            totalChecks,
            successfulChecks,
            successPercentage: `${successPercentage}%`,
            failedChecks,
            failurePercentage: `${failurePercentage}%`,
            statusCodeDistribution: statusCodeDistribution.map(item => ({
                statusCode: item._id,
                count: item.count,
                percentage: totalChecks > 0 ? `${(((item.count / totalChecks) * 100) || 0).toFixed(2)}%` : '0.00%',
            })),
            uptimePerUrl: uptimePerUrl.map(item => ({
                url: item._id,
                successCount: item.successCount,
                totalCount: item.totalCount,
                uptimePercentage: `${(item.uptimePercentage || 0).toFixed(2)}%`,
            })),
            checksOverTime: checksOverTime.map(item => ({
                period: formatPeriod(item._id, groupBy),
                count: item.total,
                averageResponseTime: `${(item.averageResponseTime || 0).toFixed(2)}ms`,
            })),
            responseTimeDistribution: responseTimeDistribution.map(item => ({
                range: formatResponseTimeRange(item._id),
                count: item.count,
                averageResponseTime: item.averageResponseTime ? `${item.averageResponseTime.toFixed(2)}ms` : 'N/A',
            })),
            topSlowestUrls: topSlowestUrls.map(item => ({
                url: item._id,
                averageResponseTime: `${(item.averageResponseTime || 0).toFixed(2)}ms`,
                totalChecks: item.totalChecks,
            })),
            recentIssues,
        };

        // Send the analytics data as a JSON response
        res.status(200).json({ analytics });
    } catch (error) {
        if (error instanceof z.ZodError) {
            // If validation fails, send a 400 response with error details
            return res.status(400).json({
                message: 'Invalid query parameters',
                errors: error.errors.map((err) => ({
                    field: err.path.join('.'),
                    message: err.message,
                })),
            });
        }

        // Log unexpected errors and send a 500 response
        logger.error('Get Analytics Error:', error);
        res.status(500).json({ message: 'Internal server error' });
    }
};

/**
 * Helper functions for formatting
 */

/**
 * Formats the period string based on the groupBy parameter.
 *
 * @param {Object} periodObj - Object containing date parts.
 * @param {string} groupBy - Grouping parameter ('hour', 'day', 'week', 'month').
 * @returns {string} - Formatted period string.
 */
const formatPeriod = (periodObj, groupBy) => {
    const { year, month, week, day, hour } = periodObj;
    switch (groupBy) {
        case 'hour':
            return `${month}/${day}/${year} ${hour}:00`;
        case 'day':
            return `${month}/${day}/${year}`;
        case 'week':
            return `Week ${week}, ${year}`;
        case 'month':
            return `${month}/${year}`;
        default:
            return `${month}/${day}/${year}`;
    }
};

/**
 * Formats the response time range for distribution buckets.
 *
 * @param {string|number} range - The range identifier from the aggregation.
 * @returns {string} - Formatted range string.
 */
const formatResponseTimeRange = (range) => {
    if (range === '5000+') return '5000+ms';
    return `${range[0]}-${range[1]}ms`;
};

/**
 * Returns the MongoDB aggregation expression based on the groupBy parameter.
 *
 * @param {string} groupBy - Grouping parameter ('hour', 'day', 'week', 'month').
 * @returns {Object} - Aggregation expression.
 */
const getPeriodExpression = (groupBy) => ({
    hour: {
        year: { $year: '$checkedAt' },
        month: { $month: '$checkedAt' },
        day: { $dayOfMonth: '$checkedAt' },
        hour: { $hour: '$checkedAt' },
    },
    day: {
        year: { $year: '$checkedAt' },
        month: { $month: '$checkedAt' },
        day: { $dayOfMonth: '$checkedAt' },
    },
    week: {
        year: { $year: '$checkedAt' },
        week: { $week: '$checkedAt' },
    },
    month: {
        year: { $year: '$checkedAt' },
        month: { $month: '$checkedAt' },
    },
}[groupBy]);
"""
"""
// server.js

const express = require('express');
const dotenv = require('dotenv');
const helmet = require('helmet');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const path = require('path');
const connectDB = require('./config/db');
const errorHandler = require('./middlewares/errorHandler');
const authRoutes = require('./routes/authRoutes');
const userRoutes = require('./routes/userRoutes');
const monitorService = require('./services/monitorService');
const logger = require('./utils/logger');
// Load environment variables
dotenv.config();

// Initialize Express
const app = express();

// Connect to MongoDB
connectDB();

// Middleware
app.use(express.json());
app.use(helmet());
app.use(cors({
    origin: ['http://localhost:3000'], // Replace with your frontend domain
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    credentials: true,
}));

// Rate Limiting
const authLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100, // limit each IP to 100 requests per windowMs
    message: 'Too many requests from this IP, please try again after 15 minutes',
});

app.use('/api/auth/signup', authLimiter);
app.use('/api/auth/login', authLimiter);
app.use('/api/user/settings', authLimiter);
app.use('/api/user/logs', authLimiter);

// Routes
app.use('/api/auth', authRoutes);
app.use('/api/user', userRoutes);

// Global Error Handler
app.use(errorHandler);

// Start Monitoring for Existing Users
monitorService.initializeMonitoring();



// Start Server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    logger.info(`Server is running on port ${PORT}`);
});

// Handle graceful shutdown
const gracefulShutdown = () => {
    logger.info('Received shutdown signal. Shutting down gracefully...');
    monitorService.gracefulShutdown();
    
    setTimeout(() => {
        logger.info('Shutdown complete. Exiting process.');
        process.exit(0);
    }, 1000);
};

process.on('SIGTERM', gracefulShutdown);
process.on('SIGINT', gracefulShutdown);

"""
"""
// routes/userRoutes.js

const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
const authenticate = require('../middlewares/authenticate');
const ensureVerified = require('../middlewares/ensureVerified'); // We'll create this middleware

// Apply both authentication and verification checks
router.put('/settings', authenticate, ensureVerified, userController.updateSettings);
router.get('/logs', authenticate, ensureVerified, userController.getUserLogs);

// **New Routes for Monitoring Control**
router.post('/monitor/start', authenticate, ensureVerified, userController.startMonitoring);
router.post('/monitor/stop', authenticate, ensureVerified, userController.stopMonitoring);

// **New Route for Analytics**
router.get('/analytics', authenticate, ensureVerified, userController.getAnalytics);

module.exports = router;
"""