
// text/x-generic user.js ( UTF-8 Unicode text, with CRLF line terminators )
const model = require('../Model');
const jwt = require("jsonwebtoken");
const bcrypt = require('bcrypt');
const online_users= require('../config/context');
require('dotenv').config();
const crypto = require('crypto');
const sendOtp = require('../config/sendEmail');
const { error } = require('console');
const { default: mongoose } = require('mongoose');
// const crypto = require('crypto');
// const CryptoJS = require('crypto-js');


const serviceId = process.env.SERVICE_ID;
const otpTemplateId = process.env.OTP_TEMPLATE_ID;
const userId = process.env.USER_ID;
const accessToken = process.env.ACCESS_TOKEN;

const generateRandomOtp = () => {
    return Math.floor(100000 + Math.random() * 900000).toString(); // Generate a 6-digit random OTP
};

const algorithm = 'aes-256-cbc';
// const accessToken = process.env.AC/]CESS_TOKEN;
const secret = process.env.SECRET_KEY; // Replace this with your secret

// Encryption function
function encrypt(userId) {
    const iv = crypto.randomBytes(16); // Initialization vector
    const cipher = crypto.createCipheriv(algorithm, crypto.scryptSync(secret, 'salt', 32), iv);

    let encrypted = cipher.update(userId, 'utf8', 'hex');
    encrypted += cipher.final('hex');

    return `${iv.toString('hex')}:${encrypted}`;
}

// Decryption function
function decrypt(encrypted) {
    const [iv, content] = encrypted.split(':');

    const decipher = crypto.createDecipheriv(
        algorithm,
        crypto.scryptSync(secret, 'salt', 32),
        Buffer.from(iv, 'hex')
    );

    let decrypted = decipher.update(content, 'hex', 'utf8');
    decrypted += decipher.final('utf8');

    return decrypted;
}

const encryptionKey = Buffer.from(process.env.ENCRYPTION_KEY, 'hex'); // Replace with securely stored key
const ivLength = 16;

// Function to encrypt the token
function encryptToken(token) {
    const iv = crypto.randomBytes(ivLength);
    const cipher = crypto.createCipheriv('aes-256-cbc', encryptionKey, iv);
    let encrypted = cipher.update(token, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    return `${iv.toString('hex')}:${encrypted}`;
}


// const encryptToken = (token) => {
//     return CryptoJS.AES.encrypt(token, process.env.ENCRYPTION_KEY).toString();
// };
const userController = {
    getAllUsers: async (req, res) => {
        try {
            // const id = req.user.id;
            const users = await model.User.find();
            res.status(200).json(users);
        } catch (err) {
            res.status(500).json({ error: 'Failed to fetch users' });
        }
    },

    createUser: async (req, res) => {
        console.log("res in body ", req.body);

        const { name, email,promoCode } = req.body; // Get only the email from the request body

        try {
            // Check if the email already exists
            const existingUser = await model.User.findOne({ email });
            if (existingUser) {
                return res.status(400).json({ success: false, error: 'Email already exists' });
            }
            let companyId;
            let allowedUsers;
            
            if (promoCode) {
                console.log("PromoCode provided:", promoCode);
            
                // Step 1: Search for the promoCode in the User table
                const userWithPromoCode = await model.User.findOne({ promoCode });
                if (!userWithPromoCode) {
                    return res.status(400).json({ success: false, error: 'Invalid promo code' });
                }
            
                // Step 2: Retrieve the CompanyId from the user record
                companyId = userWithPromoCode.CompanyId;
                if (!companyId) {
                    return res.status(400).json({ success: false, error: 'No associated company found for this promo code' });
                }
            
                // Step 3: Fetch the "AllowedUsers" from the Company table using the CompanyId
                const company = await model.CompanyandUser.findOne({ _id: companyId });
                if (!company) {
                    return res.status(400).json({ success: false, error: 'Company not found' });
                }
            
                allowedUsers = company.AllowedUsers; // Get the allowed user count for the company
            
                // Step 4: Use the UserId (adminId) from the userWithPromoCode to find users with adminId matching this ID
                const adminId = userWithPromoCode._id; // Use the ID of the user with the promo code
                console.log("admin id ", adminId);
                
                const userCount = await model.User.countDocuments({ AdminId:adminId }); // Count users associated with this admin ID
              console.log("condition check",userCount,allowedUsers);
              
                // Step 5: Check if the user count is within the allowed limit
                if (userCount >= allowedUsers) {
                    return res.status(400).json({ success: false, error: 'User limit reached for this promo code' });
                }
            }
            
            let otp = generateRandomOtp();
            const expiresIn = 15 * 60 * 1000; // 15 minutes expiration time
            const expiresAt = new Date(Date.now() + expiresIn);
            let otpEntry = await model.Otp.findOne({ email });

            if (otpEntry) {
                // If exists, update the OTP and expiration
                otpEntry.otp = otp;
                otpEntry.expiresAt = expiresAt;
                await otpEntry.save();
                // console.log('OTP updated for existing email:', email);
            } else {
                // If not, create a new OTP record
                otpEntry = await model.Otp.create({ email, otp, expiresAt });
                await otpEntry.save();
                // console.log('New OTP created for email:', email);
            }

            var data = {
                service_id: serviceId,
                template_id: otpTemplateId ,
                user_id: userId,
                accessToken: accessToken,
                template_params: {
                    'otp': otp,
                    'to_email': email,
                    'to_name': name,
                }
            };
            // Send the OTP email

            await sendOtp(data);

            res.status(200).json({
                success: true,
                message: 'OTP sent to your email for verification.'
            });
        } catch (err) {
            console.error("Error in createUser:", err);
            res.status(500).json({ success: false, error: 'Failed to create user' });
        }
    },

    createSuperAdmin: async (payload) => {
        const { email, name, password, country, phone, companyName, companyLocation } = payload;
    
        try {   
            // Check if the user already exists
            const existingUser = await model.User.findOne({ email });
            if (existingUser) {
                // Log the error and return false indicating failure
                console.error(`User already exists with email: ${email}`);
                return { success: false, message: "User already exists" }; // Return a clear message
            }
    
            // Hash the password
            const hashedPassword = await bcrypt.hash(password, 10);
    
            // Create new company
            const newCompany = await model.CompanyandUser.create({
                 country, phone, companyName, companyLocation
            });
    
            // Create new user
            let newUser = await model.User.create({
                name,
                email,
                password: hashedPassword,
                credit: 1000,
                plan: 1,
                role: 'superadmin',
                CompanyId: newCompany.id,
            });
    
            // Success response
            return { success: true, message: "Super admin created successfully" };
        } catch (err) {
            console.error("Error in createSuperAdmin:", err);
            return { success: false, message: "An error occurred while creating super admin." }; // Return error message
        }
    },
    

    verifyOtpAndCreateUser: async (req, res) => {
     console.log("respoce ", req.body);
     
        const { email, otp, name, password, country, phone, companyName, companyLocation, promoCode } = req.body;
    
        try {
            // Verify the OTP
            console.log("Body of create user:", req.body);
            
            const otpRecord = await model.Otp.findOne({ email: email });
            
            if (!otpRecord) {
                return res.status(400).json({ success: false, error: 'OTP not found for this email' });
            }
    
            // Check OTP and expiration
            if (Date.now() > otpRecord.expiresAt || otp !== otpRecord.otp) {
                return res.status(400).json({ success: false, error: 'Invalid or expired OTP' });
            }
    
            // Optionally, delete the OTP after successful verification
            await otpRecord.deleteOne();
        
            // Check if the company name already exists
            const existingCompany = await model.User.findOne({ companyName: companyName.toLowerCase() });
            if (existingCompany) {
                return res.status(400).json({ success: false, error: 'Company name already exists' });
            }
    
            let adminId;
            if (promoCode) {
                console.log("Promo code received:", promoCode);
    
                // Find the admin user with the matching promo code
                const adminUser = await model.User.findOne({ promoCode });
    
                console.log("Admin user found for promo code:", adminUser); 
                if (adminUser) {
                    adminId = adminUser.id;
                } 
                else {
                    // If promo code is invalid, handle the error
                    return res.status(400).json({ success: false, error: 'Invalid promo code' });
                }
            }
    
            // Hash the password
            const hashedPassword = await bcrypt.hash(password, 10);
    
            // Create a new company record
            const newCompany = await model.CompanyandUser.create({
                 country, phone, companyName, companyLocation
            });
    
            // Create the new user
            let newUser = await model.User.create({
                name:name.toLowerCase(),
                email: email.toLowerCase(),
                password: hashedPassword,
                credit: 0,
                plan: 1,
                role: adminId ? 'user' : null,
                CompanyId: newCompany.id,
                AdminId: adminId
            });
    
            // Success response
            res.status(201).json({
                success: true,
                message: 'User created successfully.',
                status: promoCode ? 1 : 0, 
            });
        } catch (err) {
            // Proper error handling with a clear message
            console.error("Error in verifyOtpAndCreateUser:", err.message);
            res.status(500).json({ success: false, error: `Failed to create user after OTP verification: ${err.message}` });
        }
    },
    
    

    loginUser: async (req, res) => {
    const { email, password } = req.body;
    
    try {
        // Step 1: Check if the user exists
        const user = await model.User.findOne({ email: email.toLowerCase() });
        if (!user) {
            return res.status(404).json({ success: false, message: 'User not found' });
        }

        // Step 2: Check password (uncomment when ready)
        // const isPasswordMatch = await bcrypt.compare(password, user.password);
        // if (!isPasswordMatch) {
        //     return res.status(404).json({ success: false, message: 'Invalid password' });
        // }

        // Step 3: Generate OTP
        const otp = generateRandomOtp();
        await model.User.findByIdAndUpdate(user._id, { otp }, { new: true });

        // Step 4: Send OTP via email
        const emailData = {
            service_id: serviceId,
            template_id: otpTemplateId,
            user_id: userId,
            accessToken: accessToken,
            template_params: {
                'otp': otp,
                'to_email': email,
                'to_name': user.name,
            }
        };
        await sendOtp(emailData);

        // Return response WITHOUT token (we'll issue after OTP verification)
        return res.status(200).json({
            success: true,
            message: 'OTP sent to your email',
            otpSent: true,
            userId: user._id // Include user ID for OTP verification
        });
        
    } catch (err) {
        console.error('Error during login:', err);
        return res.status(500).json({ success: false, message: 'Server error' });
    }
},
    // verifyOtp: async (req, res) => {
    //     console.log("login data ", req.body);

    //     const { email, otp } = req.body;

    //     try {
    //         // Step 5: Find the user by email and check OTP
    //         const user = await model.User.findOne({ email: email.toLowerCase() });
    //         if (!user || user.otp != otp) {
    //             return res.status(401).json({ success: false, message: 'Invalid OTP' });
    //         }

    //         // Step 6: Generate JWT token after successful OTP verification
    //         const updatedNumber = user.number ? user.number + 1 : 1;
    //         const token = jwt.sign(
    //             { id: user._id, email: user.email, role: user.role, number: updatedNumber },
    //             secret, // Secret key
    //             { expiresIn: '1h' }
    //         );

    //         // Update user's number and clear OTP from database
    //         await model.User.findByIdAndUpdate(
    //             user._id,
    //             { $set: { number: updatedNumber, otp: null } },
    //             { new: true }
    //         );

    //         const now = Date.now();
    //         console.log("online_users",online_users);

    //         // Check if the user needs to select a plan
    //         if (now > user.subscriptionValid) {
    //             return res.status(200).json({
    //                 success: true,
    //                 message: 'Please select a plan before accessing your dashboard. An email has been sent with further instructions.',
    //                 planSelected: false,
    //                 data: {
    //                     token: token,
    //                     role: user.role,
    //                     id:user.id
    //                 }
    //             });
    //         }
    //         console.log("role is ", user);
            
    //       if(user.role === null){
    //         console.log("role null");
            
    //         return res.status(200).json({
    //                 success: true,
    //                 message: 'Please select a plan before accessing your dashboard. An email has been sent with further instructions.',
    //                 planSelected: false,
    //                 data: {
    //                     token: token,
    //                     role: user.role,
    //                     id:user.id
    //                 }
    //             });
    //       }
    //         // Successful login with plan already selected
    //         return res.status(200).json({
    //             success: true,
    //             message: 'Login successful',
    //             planSelected: true,
    //             data: {
    //                 token: token,
    //                 role: user.role,
    //                 name :user.name,
    //                 id:user.id
    //             }
    //         });

    //     } catch (err) {
    //         console.error('Error during OTP verification:', err);
    //         return res.status(500).json({ success: false, message: 'Server error' });
    //     }
    // },

    verifyOtp: async (req, res) => {
        console.log("login data ", req.body);

        const { email, otp } = req.body;

        try {
            // Step 5: Find the user by email and check OTP
            const user = await model.User.findOne({ email: email.toLowerCase() });
            if (!user || user.otp != otp) {
                return res.status(401).json({ success: false, message: 'Invalid OTP' });
            }

            // Step 6: Generate JWT token after successful OTP verification
            const updatedNumber = user.number ? user.number + 1 : 1;
            const token = jwt.sign(
                { id: user._id, email: user.email, role: user.role, number: user.number,version:user.T_Version },
                process.env.SECRET_KEY, // Secret key
                { expiresIn: '5d' }
            );

            // Encrypt the JWT token
            const encryptedToken = encryptToken(token);

            // Update user's number and clear OTP from database
            await model.User.findByIdAndUpdate(
                user._id,
                { $set: { number: updatedNumber, otp: null } },
                { new: true }
            );

            const now = Date.now();
            console.log("online_users", online_users);

            // Check if the user needs to select a plan
            if (now > user.subscriptionValid) {
                return res.status(200).json({
                    success: true,
                    message: 'Please select a plan before accessing your dashboard. An email has been sent with further instructions.',
                    planSelected: false,
                    data: {
                        token: encryptedToken,
                        role: user.role,
                        id: user.id
                    }
                });
            }
            console.log("role is ", user);

            if (user.role === null) {
                console.log("role null");

                return res.status(200).json({
                    success: true,
                    message: 'Please select a plan before accessing your dashboard. An email has been sent with further instructions.',
                    planSelected: false,
                    data: {
                        token: encryptedToken,
                        role: user.role,
                        id: user.id
                    }
                });
            }

            // Successful login with plan already selected
            return res.status(200).json({
                success: true,
                message: 'Login successful',
                planSelected: true,
                data: {
                    token: encryptedToken,
                    role: user.role,
                    name: user.name,
                    id: user.id
                }
            });

        } catch (err) {
            console.error('Error during OTP verification:', err);
            return res.status(500).json({ success: false, message: 'Server error' });
        }
    },


  // Step 1: Send OTP for password reset
  sendResetOtp: async (req, res) => {
   
    
    var { email } = req.body;
    email = email.toLowerCase();
    console.log("email is ", req.body);
    try {
      // Check if the user exists
      const user = await model.User.findOne({ email });
      if (!user) {
        return res.status(404).json({ success: false, message: 'User not found' });
      }

      // Generate and save OTP
      const otp = generateRandomOtp();
      console.log("user is ", user);
      
      const data = await model.User.findByIdAndUpdate(user._id, { otp }, { new: true });
  console.log("data is", data);
  
     // Send OTP via email
      const emailData = {
        service_id: serviceId,
        template_id: otpTemplateId,
        user_id: userId,
        accessToken: accessToken,
        template_params: {
          'otp': otp,
          'to_email': email,
          'to_name': user.name,
        },
      };
      await sendOtp(emailData);

      return res.status(200).json({
        success: true,
        message: 'OTP sent to your email. Please verify to reset your password.',
      });
    } catch (err) {
      console.error('Error during password reset OTP sending:', err);
      return res.status(500).json({ success: false, message: 'Server error' });
    }
  },

  // Step 2: Verify OTP and update password
  verifyResetOtp: async (req, res) => {
    const { email, otp, newPassword } = req.body;

    try {
      // Find the user by email and verify OTP
      const user = await model.User.findOne({ email });
      console.log("user ",user.otp);
      console.log("otp is ", otp );
      
      if (user.otp!=otp) {
        return res.status(401).json({ success: false, message: 'Invalid OTP' });
      }

      // Hash the new password
      const hashedPassword = await bcrypt.hash(newPassword, 10);

      // Update password and clear OTP
      const pass  = await model.User.findByIdAndUpdate(
        user._id,
        { $set: { password: hashedPassword},$inc: {
            T_Version: 1, // Increment the T_Version field by 1
        } },
        { new: true }
      );
      
console.log("pass: " + pass);

      return res.status(200).json({
        success: true,
        message: 'Password updated successfully. You can now log in with your new password.',
      });
    } catch (err) {
      console.error('Error during password reset:', err);
      return res.status(500).json({ success: false, message: 'Server error' });
    }
  },

    GetCredit: async (req, res) => {
        const id = req.user.id;  // The id of the authenticated user
        console.log("id is ", id);

        try {
            // Find the user in the User table by id
            const user = await model.User.findOne({ _id: id });

            // Check if the user exists
            if (!user) {
                return res.status(404).json({ success: false, message: 'User not found' });
            }

            // If the user is found, extract the name and credit
            const { name, credit } = user;

            // Return the user data
            res.status(200).json({
                success: true,
                data: {
                    name,
                    credit
                }
            });
        } catch (err) {
            console.error('Error fetching user credit:', err);
            res.status(500).json({ success: false, message: 'Server error' });
        }
    },

    HistoryHtml: async (req, res) => {
        const { vin, id } = req.params; // Get vin and optionally userId (if admin)

        let userId;

        // Extract user ID and role from token (assuming req.user is populated via middleware)
        const userRole = req.user.role; // Assuming req.user contains the role
        userId = req.user.id; // Default to user ID from token

        try {
            // Check if the user has a role of 'user' or 'admin'
            if (userRole !== 'user' && userRole !== 'admin') {
                return res.status(403).json({ message: 'Access denied. Only users or admins can perform this action.' });
            }

            // If the user is an admin, use the userId passed in params instead of the one from token
            if (userRole === 'admin' && id) {
                userId = id; // Admin can specify another user ID via the route parameter
            } else if (userRole === 'user') {
                userId = req.user.id; // Use the user ID from the token for regular users
            }

            console.log("VIN number:", vin);
            console.log("UserID:", userId);
            console.log(
                "id and vin", id, vin
            );

            // Check in the 'userhistory' table if the VIN exists for the specific user
            const userHistoryEntry = await model.UserHistory.findOne({ user: userId, searchVin: vin });

            if (!userHistoryEntry) {
                return res.status(404).json({ message: `VIN ${vin} not found in user's history.` });
            }

            // Check if the VIN already exists in the HtmlData table
            const htmlEntry = await model.HtmlData.findOne({ vin });

            // If the VIN is found in the database, return the HTML data
            if (htmlEntry) {
                return res.status(200).json({ message: 'VIN found in database', data: htmlEntry });
            }

            // If the VIN is not found, return a response indicating that
            return res.status(404).json({ message: 'No VIN number found in the database' });

        } catch (error) {
            // Handle any errors that occur during the database search or role check
            console.error('Error:', error.message);
            res.status(500).json({ message: 'An error occurred while processing the request', error: error.message });
        }
    },


    GetUserHistory: async (req, res) => {
        try {
           
           
           
    
            
            const role = req.user.role;  // Get the role from the request
            let id;

            // If the role is 'user', get id from the authenticated user
            if (role === 'user') {
                id = req.user._id;
            }
            // If the role is 'admin' or 'superadmin', get id from the URL params
            else if (role === 'admin' || role === 'superadmin') {
                id = req.params.id;
            } else {
                return res.status(403).json({ success: false, message: 'Unauthorized access' });
            }

            console.log("User ID is:", id);

            // Check if id is valid before proceeding
            if (!id || id === "null") {
                return res.status(400).json({ success: false, message: "id is requred"});
            }

            // Find all user histories by user ID in the 'userhistories' table
            const userHistories = await model.UserHistory.find(
                {
                    user: new mongoose.Types.ObjectId(id), // Search by userId
                    // $expr: { $eq: [{ $month: "$date" }, monthNumber] } // Filter by month number
                },
                { searchVin: 1, date: 1 } // Only include vin and date fields in the result
            ).sort({
                date: -1
            });

            // Check if user histories are found
            if (!userHistories || userHistories.length === 0) {
                return res.status(404).json({ success: false, message: 'User history not found' });
            }

            // Return the vins and dates from the user histories
            return res.status(200).json({
                success: true,
                data: userHistories.map(history => ({
                    vin: history.searchVin,
                    date: history.date
                }))
            });
        } catch (err) {
            console.error('Error fetching user history:', err);
            return res.status(500).json({ success: false, message: 'Server error' });
        }
    },


    getAllUsersWithSearchCount: async (req, res) => {
        try {
            const role = req.user.role;
            let userId;
            if (role === "superadmin") {
                userId = req.params.id;
            } else if (role === "admin") {
                userId = req.user.id;
            }
            console.log("id of admin or super admin", userId);
    
            const month = req.params.month === "null" ? null : parseInt(req.params.month);
    
            if (month && (isNaN(month) || month < 1 || month > 12)) {
                return res.status(400).json({
                    success: false,
                    message: 'Invalid month number. Please provide a month between 1 and 12.',
                });
            }
    
            // Find the user by ID to get their `userCompanyId`
            const user = await model.User.findById(userId);
            if (!user) {
                return res.status(404).json({
                    success: false,
                    message: 'User not found.',
                });
            }
            console.log("user all  ", user);
    
            // Fetch users that match the specific `userCompanyId` of the requested user
            const specificCompanyUsers = await model.User.find({
                AdminId: user._id
            });
            console.log("users are ", specificCompanyUsers);
    
            // Retrieve user data with search counts and history info
            const usersWithSearchCount = await Promise.all(specificCompanyUsers.map(async (companyUser) => {
                let condition = { user: companyUser._id };
                if (month) {
                    const startDate = new Date(new Date().getFullYear(), month - 1, 1);
                    const endDate = new Date(new Date().getFullYear(), month, 1);
                    condition = {
                        user: companyUser._id,
                        date: { $gte: startDate, $lt: endDate },
                    };
                }
            
                const searchCount = await model.UserHistory.countDocuments(condition);
                const userHistoryCount = await model.UserHistory.countDocuments({ user: companyUser._id });
            
                return month && searchCount === 0 ? null : {
                    id: companyUser._id,
                    name: companyUser.name,
                    email: companyUser.email,
                    totalSearches: searchCount,
                    userHistoryCount: userHistoryCount,
                };
            }));
            
            // Add the admin's own search history if the role is admin
            if (role === "admin") {
                let condition = { user: user._id }; // Admin's own ID
                if (month) {
                    const startDate = new Date(new Date().getFullYear(), month - 1, 1);
                    const endDate = new Date(new Date().getFullYear(), month, 1);
                    condition = {
                        user: user._id,
                        date: { $gte: startDate, $lt: endDate },
                    };
                }
            
                const adminSearchCount = await model.UserHistory.countDocuments(condition);
                const adminHistoryCount = await model.UserHistory.countDocuments({ user: user._id });
            
                usersWithSearchCount.push({
                    id: user._id,
                    name: user.name,
                    email: user.email,
                    totalSearches: adminSearchCount,
                    userHistoryCount: adminHistoryCount,
                });
            }
            
    
            // Filter out null values if month is specified
            const filteredUsers = month ? usersWithSearchCount.filter(user => user !== null) : usersWithSearchCount;
    
            // Return the users with their search counts and history info
            return res.status(200).json({
                success: true,
                message: month ? 'Users with search counts fetched successfully' : 'All users with their search counts fetched successfully',
                data: filteredUsers,
            });
        } catch (err) {
            console.error('Error fetching users with search counts:', err);
            return res.status(500).json({
                success: false,
                message: 'Failed to fetch users with search counts',
                error: err.message,
            });
        }
    },
    
    // getAllUsersWithSearchCount: async (req, res) => {
    //     try {
    //         const userId = req.params.id; // User ID passed in params
    //         const month = req.params.month === "null" ? null : parseInt(req.params.month);

    //         // Step 1: Find the user in the User table by ID
    //         const user = await model.User.findById(userId);

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

    //         // Step 2: Get the CompanyandUserId from the user
    //         const companyAndUserId = user.CompanyandUserId;

    //         // Step 3: Find all users with role 'user' and matching userCompanyId
    //         const matchingUsers = await model.User.find({
    //             role: 'user',
    //             userCompanyId: companyAndUserId
    //         });

    //         if (!matchingUsers.length) {
    //             return res.status(404).json({
    //                 success: false,
    //                 message: 'No users found with the specified criteria',
    //             });
    //         }

    //         // Step 4: Prepare an array to hold user history counts
    //         const userHistoryCounts = [];

    //         // Step 5: Check history for each matching user
    //         for (const match of matchingUsers) {
    //             // Define the condition for counting based on month
    //             let condition = { CompanyandUserId: match.CompanyandUserId };

    //             if (month) {
    //                 if (isNaN(month) || month < 1 || month > 12) {
    //                     return res.status(400).json({
    //                         success: false,
    //                         message: 'Invalid month number. Please provide a month between 1 and 12.',
    //                     });
    //                 }

    //                 const startDate = new Date(new Date().getFullYear(), month - 1, 1);
    //                 const endDate = new Date(new Date().getFullYear(), month, 1);

    //                 condition = {
    //                     CompanyandUserId: match.CompanyandUserId,
    //                     createdAt: {
    //                         $gte: startDate,
    //                         $lt: endDate,
    //                     },
    //                 };
    //             }

    //             // Check if model.History is defined
    //             if (!model.History) {
    //                 return res.status(500).json({
    //                     success: false,
    //                     message: 'History model is not defined',
    //                 });
    //             }

    //             // Count the user history for the specified user and condition
    //             const historyCount = await model.UserHistory.countDocuments(condition);

    //             userHistoryCounts.push({
    //                 userId: match._id,
    //                 companyAndUserId: match.CompanyandUserId,
    //                 historyCount: historyCount,
    //             });
    //         }

    //         // Return the results
    //         return res.status(200).json({
    //             success: true,
    //             message: 'User history counts retrieved successfully',
    //             data: userHistoryCounts, // Returns an array of user history counts
    //         });

    //     } catch (err) {
    //         console.log("error is ",err);

    //         console.error('Error retrieving user history counts:', err);
    //         return res.status(500).json({
    //             success: false,
    //             message: 'Failed to retrieve user history counts',
    //             error: err.message,
    //         });
    //     }
    // },






    getAllUsersWithMonthlyStats: async (req, res) => {
        const { month } = req.params; // Assume you pass the month as a URL parameter

        if (month < 1 || month > 12) {
            return res.status(400).json({
                success: false,
                message: 'Invalid month. Please provide a number between 1 and 12.',
            });
        }

        try {
            // Retrieve all users from the User table
            const users = await model.User.find();

            // Initialize an array to hold the user data with search counts for the specified month
            const usersWithSearchCount = await Promise.all(users.map(async (user) => {
                // Count search history for each user based on their user ID and filter by month
                const searchCount = await model.UserHistory.countDocuments({
                    user: user._id,
                    // Match the month in the createdAt field
                    createdAt: {
                        $gte: new Date(new Date().getFullYear(), month - 1, 1), // Start of the month
                        $lt: new Date(new Date().getFullYear(), month, 1), // Start of the next month
                    },
                });

                return {
                    id: user._id,
                    name: user.name,
                    email: user.email,
                    totalSearches: searchCount,
                };
            }));

            // Return the users with their search counts in the response
            return res.status(200).json({
                success: true,
                message: 'Users with search counts for the specified month fetched successfully',
                data: usersWithSearchCount,
            });
        } catch (err) {
            console.error('Error fetching users with search counts:', err);
            return res.status(500).json({
                success: false,
                message: 'Failed to fetch users with search counts',
                error: err.message,
            });
        }
    },





    updateUserAndCompanyData: async (req, res) => {
        console.log("body data of plans ", req.body);

        const { title } = req.body;
        const userId = req.user.id;

        try {
            // Search for the title in the Plans collection
            const plan = await model.userplans.findOne({ title });

            if (!plan) {
                return res.status(404).json({ success: false, message: 'Plan title not found' });
            }

            // Get the role and allowedEmployees from the plan document
            const { role, allowedEmployees } = plan;

            if (!role) {
                return res.status(400).json({ success: false, message: 'Role not specified in plan' });
            }

            // Find the user by ID in the User collection
            const user = await model.User.findById(userId);

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

            // Update the user's role in the User collection
            const updatedUser = await model.User.findByIdAndUpdate(
                userId,
                { $set: { role, plan: 1 } },
                { new: true }  // Returns the updated document
            );

            // Get CompanyandUserId from the user document
            const { CompanyandUserId } = updatedUser;

            if (!CompanyandUserId) {
                return res.status(404).json({ success: false, message: 'Associated CompanyandUserId not found' });
            }

            // Update the company's TotalUserRemaining field in the CompanyandUser collection
            const updatedCompanyData = await model.CompanyandUser.findByIdAndUpdate(
                CompanyandUserId,
                { $set: { TotalUserRemaining: allowedEmployees } },
                { new: true }  // Returns the updated document
            );

            // Generate JWT token with updated user information
            const token = jwt.sign(
                {
                    id: updatedUser._id,
                    email: updatedUser.email,
                    role: updatedUser.role,
                    number: updatedUser.number, // Assuming updatedNumber refers to updatedUser.number
                },
                secret, // Secret key
                { expiresIn: '5d' } // Token expiration
            );

            return res.status(200).json({
                success: true,
                message: `User role updated to ${role} and company data updated`,
                data: { updatedUser, updatedCompanyData },
                token: {
                    token: token,
                    role: updatedUser.role
                }


            });
        } catch (err) {
            console.error('Error updating user role and company data:', err);
            res.status(500).json({ success: false, message: 'Server error' });
        }
    },



    // createSuperAdmin: async function () {
    //     const superAdminEmail = 'superadmin@example.com';
    //     const superAdminPassword = 'superadmin123';

    //     const existingAdmin = await model.User.findOne({ where: { role: 'superadmin' } });
    //     if (!existingAdmin) {

    //       const hashedPassword = await bcrypt.hash(superAdminPassword, 10);
    //       await model.User.create({
    //         email: superAdminEmail,
    //         password: hashedPassword,
    //         role: 'superadmin',
    //       });

    //       console.log("SuperAdmin created with email", superAdminEmail);
    //     }
    //   }

   updateReminder: async (req, res) => {
        try {
            console.log("req body is ", req.body);
            
            const userId = req.body.userId; // Extract userId from req.user.id
            const { remainder } = req.body; // Extract reminder from the request body
    
            // Validate the reminder input
            if (!remainder) {
                return res.status(400).json({ success: false, message: 'Reminder is required' });
            }
    
            // Find the user by userId
            const user = await model.User.findById(userId);
           console.log("user before ", user );
           
            // If user is not found, return an error
            if (!user) {
                return res.status(404).json({ success: false, message: 'User not found' });
            }
    
            // Update the reminder for the user
            user.remainder = remainder; // Assuming the reminder field exists in your User model
           const after=await user.save(); // Save the updated user document
            console.log("user after ", after ); 
            // Return success response
            res.status(200).json({ success: true, message: 'Reminder updated successfully', data: user });
        } catch (error) {
            console.error('Error updating reminder:', error);
            res.status(500).json({ success: false, message: 'Internal server error' });
        }
    },
    getReminder: async (req, res) => {
        try {
            const userId = req.params.userId; // Extract userId from req.user.id
    
            // Find the user by userId
            const user = await model.User.findById(userId);
    
            // If user is not found, return an error
            if (!user) {
                return res.status(404).json({ success: false, message: 'User not found' });
            }
    
            // Extract the reminder from the user document
            const remainder = user.remainder;
    
            // Return the reminder in the response
            res.status(200).json({ success: true, message: 'Reminder fetched successfully', data: { remainder } });
        } catch (error) {
            console.error('Error fetching reminder:', error);
            res.status(500).json({ success: false, message: 'Internal server error' });
        }
    }




};

module.exports = userController;