const model = require('../Model');
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
const online_users = require('../config/context');
const models = require('../Model');

const adminController = {

  generateRefcode: async (req, res) => {
    if (req.user.role !== "admin") {
      return res.status(404).json({ message: 'not allowed' });

    }
    try {
      const generateCode = () => {
        // Generate a random 6-digit code
        const newCode = Math.floor(100000 + Math.random() * 900000);
        return newCode;
      };

      let codeExist = true;
      let code;
      while (codeExist) {
        code = generateCode();
        codeExist = await model.User.findOne({ promoCode: code })
      }

      const updatedUser = await model.User.findByIdAndUpdate(
        req.user.id,
        { promoCode: code },
        { new: true } // Return the updated document
      );

      if (updatedUser) {
        res.status(200).json({ message: 'Promo code generated and updated successfully.', promoCode: code });
      } else {
        res.status(404).json({ message: 'User not found.' });
      }
    } catch (error) {

    }
  },
  getPromoCode: async (req, res) => {
    // Check if the user has admin privileges
    if (req.user.role !== "admin") {
      return res.status(403).json({ message: 'Not allowed' });
    }

    try {
      // Retrieve the user's promo code from the database
      const user = await model.User.findById(req.user.id, 'promoCode');

      if (user) {
        res.status(200).json({ promoCode: user.promoCode });
      } else {
        res.status(404).json({ message: 'User not found.' });
      }
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: 'Server error' });
    }
  },


  getAllUsers: async (req, res) => {
    try {
      // Extract user ID from token (assuming req.user is populated via middleware)

      const role = req.user.role;
      let adminId;
      console.log("admin id", adminId)
      if (role === 'superadmin') {
        // If role is 'superadmin', get userId from params
        adminId = req.params.id;
        if (adminId) {
          const adminUser = await model.User.findById(adminId);
          adminId = adminUser ? adminUser._id : null
        }


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

      } else if (role === 'admin') {
        // If role is 'admin', get userId from req.user.id
        adminId = req.user.id;
      }

      console.log("admin id", adminId)

      // Retrieve CompanyandUserId from the admin user
      // const companyID = adminUser.CompanyandUserId;

      // Find all users with matching CompanyandUserId
      const users = await model.User.find({
        AdminId: adminId,
        role: "user"
      });
      console.log("USERS", users);

      // Prepare an array to hold user details with company info
      const usersWithCompanyInfo = await Promise.all(users.map(async (user) => {
        // Find the associated company info using CompanyandUserId
        const companyInfo = await model.CompanyandUser.findOne({
          _id: user.CompanyId
        });
        const searchCount = await model.UserHistory.countDocuments({ user: user._id });
        return {
          userId: user._id, // MongoDB uses '_id'
          name: user.name,
          email: user.email,
          markup:user.markup,
          credit: user.credit,
          createdAt: user.createdAt,
          searchCount: searchCount,
          companyInfo: companyInfo ? {
            name: companyInfo.name,
            phone: companyInfo.phone,
            country: companyInfo.country,
          } : null,
        };
      }));
console.log("company users",usersWithCompanyInfo );

      // Return the users with company info in the response
      return res.status(200).json({
        success: true,
        message: 'Users fetched successfully',
        data: {
          users: usersWithCompanyInfo,
        }
      });

    } catch (err) {
      console.error('Error fetching users:', err);
      return res.status(500).json({
        success: false,
        message: 'Failed to fetch users',
        error: err.message
      });
    }
  },

  ActiveUsers: async (req, res) => {
    try {
      // Process each user object in the array
      const result = online_users.map(user => {
        const email = user.email;  // Extract the email
        const nestedObjectsCount = user.data ? Object.keys(user.data).length : 0; // Count the length of nested objects (assuming nested data is inside `data`)

        return {
          email,
          nestedObjectsCount
        };
      });

      // Respond with the processed data
      res.status(200).json(result);
    } catch (error) {
      console.error('Error processing users:', error);
      res.status(500).json({ message: 'Server error, unable to process users.' });
    }
  },

  getAlladmin: async (req, res) => {
    console.log("hello getalladmin");
    
    try {
      // Check if the user has the required role
      if (req.user.role !== "superadmin") {
        return res.status(404).json({
          success: false,
          message: 'Not allowed',
        });
      }

      // Extract user ID from token (assuming req.user is populated via middleware)
      const userId = req.user.id;

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

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

      // Find all users with role 'admin'
      const users = await model.User.find({ role: 'admin' });

      // Prepare an array to hold user details with company and history info
      const usersWithCompanyAndHistoryInfo = await Promise.all(users.map(async (user, index) => {
        console.log("compaay id ", users[index].CompanyId);

        // Find the associated company info using CompanyId
        const companyInfo = await model.CompanyandUser.findOne({
          _id: users[index].CompanyId // Use the correct field for matching
        });

        // Count the total history records for the current admin user
        const userHistoryCount = await model.UserHistory.countDocuments({
          user: user._id // Assuming "user" in UserHistory refers to the admin's userId
        });


        // Find all users under this admin (role: "user" and adminId matches the current admin)
        const usersUnderAdmin = await model.User.find({
          AdminId: user._id
        });

        // Extract user IDs under this admin
        const userIdsUnderAdmin = usersUnderAdmin.map((user) => user._id);

        // Count total searches done by all users under this admin
        const totalSearchCount = await model.UserHistory.countDocuments({
          user: { $in: userIdsUnderAdmin },
        });
        console.log("user detial ", user);
        

        return {
          userdetail: user,
          createdAt: user.createdAt,
          userId: user._id,          // MongoDB uses '_id'
          email: user.email,          // Get the email
          sessions: user.sessionAllowed, // Get the session allowance
          markup:user.markup,
          companyInfo: companyInfo,
          userHistoryCount: userHistoryCount,
          totalSearchCount: totalSearchCount
        };
      }));

      // Return the users with company and history info in the response
      return res.status(200).json({
        success: true,
        message: 'Admin users fetched successfully',
        data: {
          users: usersWithCompanyAndHistoryInfo,
        }
      });

    } catch (err) {
      console.error('Error fetching users:', err);
      return res.status(500).json({
        success: false,
        message: 'Failed to fetch users',
        error: err.message
      });
    }
  },




 updateUser : async (req, res) => {
  try {
    // Get the user ID from the request params
    const { id } = req.params;
    console.log("Params", id);

    // Check if the requesting user has the required role
    if (req.user.role !== "superadmin" && req.user.role !== "admin") {
      return res.status(403).json({
        success: false,
        message: 'Not Allowed',
      });
    }

    // Extract the fields to update from the request body
    console.log("body is", req.body);

    const { name, email, phone, country, credit, sessions, AllowedUsers, markup } = req.body;

    if (AllowedUsers) {
      console.log("user email", email);

      // Find the user by email
      const user = await model.User.findOne({ email });
      if (!user) {
        return res.status(404).json({ error: 'User not found' });
      }

      // Count how many users have this user's id as their AdminId
      const userCount = await model.User.countDocuments({ AdminId: user._id });
      console.log("Already Users", userCount);
      console.log("Max Limit", AllowedUsers);

      if (userCount >= AllowedUsers) {
        return res.status(403).json({ error: 'Allowed user limit exceeded' });
      }
    }

    // Object to store updates for each model
    const userUpdates = await model.User.findById(id);
    const companyUpdates = await model.CompanyandUser.findById(userUpdates.CompanyId);

    // Check if the user and company were found
    if (!userUpdates || !companyUpdates) {
      return res.status(404).json({
        success: false,
        message: 'User or company not found',
      });
    }

    // Add fields to the updates object if provided in the request
    if (name) userUpdates.name = name;
    if (email) userUpdates.email = email;
    if (credit) userUpdates.credit = Number(credit);
    if (sessions) userUpdates.sessionAllowed = Number(sessions);
    if (markup) userUpdates.markup = Number(markup);
    if (phone) companyUpdates.phone = phone;
    if (country) companyUpdates.country = country;
    if (AllowedUsers) companyUpdates.AllowedUsers = Number(AllowedUsers);

    // Save the updates to the database
    console.log("user, company updates", userUpdates, companyUpdates);

    await userUpdates.save();
    await companyUpdates.save();

    // Return a success response with the updated user data
    return res.status(200).json({
      success: true,
      message: 'User updated successfully',
      data: {
        updatedUser: userUpdates,
      },
    });
  } catch (err) {
    console.error('Error updating user:', err);
    return res.status(500).json({
      success: false,
      message: 'Failed to update user',
      error: err.message,
    });
  }
},
  deleteUser: async (req, res) => {
    try {
      // Get the user ID from the request params
      const { id } = req.params; // Assuming the user ID is passed as a URL parameter
      const userid = req.user.id
      const { password } = req.body;

      if (!password) {
        return res.status(404).json({
          success: false,
          message: 'Password is required'
        })
      }

      const user = await model.User.findById(userid);

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

      console.log("password ", user);
      console.log("password send ", password)


      // Check if the provided password matches the user's password
      const isPasswordMatch = await bcrypt.compare(password, user.password);

      if (!isPasswordMatch) {
        return res.status(403).json({
          success: false,
          message: 'Incorrect password',
        });
      } // Assuming you have a method to compare passwords



      // Find the user by ID and delete them
      const deletedUser = await model.User.findByIdAndDelete(id);

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

      // Return a success message in the response
      return res.status(200).json({
        success: true,
        message: 'User deleted successfully',
        data: deletedUser, // Optionally return the deleted user data
      });
    } catch (err) {
      console.error('Error deleting user:', err);
      return res.status(500).json({
        success: false,
        message: 'Failed to delete user',
        error: err.message,
      });
    }
  },
  getOnlineUsers: async (req, res) => {
    try {
      // if(req.user.role!=="superadmin") throw new Error("Unauthorize");
      const on_users = {}
      for (const [key, value] of Object.entries(online_users)) {
        console.log(`Key: ${key}, Value: ${value}`);
        const user = await models.User.findById(key);
        console.log(user.email);
        console.log("value", value);
        const omitKey = 'socketId';

        const updatedArray = value.map(({ socketId, ...rest }) => rest

        );
        console.log(updatedArray);
        on_users[user.email] = {
          sessions: updatedArray,
          count: updatedArray.length, // Add the length of the updated array
        };
        // online_users[userId].filter(item => item["socketId"] !== socket.id)
      }
      return res.status(200).json({
        success: true,
        message: "success",
        on_users
      });
      // online_users
    } catch (error) {
      return res.status(404).json({
        success: false,
        message: error.message,
      });

    }
  },
  AllowMultipleAdmin: async (req, res) => {
    try {
      // Get the user ID and toggle value from the request params
      const { toggleValue } = req.params;
      const id = req.user.id

      // Validate toggleValue (should be either "1" or "0")
      if (toggleValue !== '1' && toggleValue !== '0') {
        return res.status(400).json({
          success: false,
          message: 'Invalid toggle value. Use 1 or 0.',
        });
      }

      // Find the user by ID and update the toggle field
      const updatedUser = await model.User.findOneAndUpdate(
        { _id: id },                        // Match the user by ID
        { Toggle: toggleValue === '1' ? 1 : 0 }, // Set toggle to 1 or 0
        { new: true }                       // Return the updated user document
      );

      // If no user is found with the given ID
      if (!updatedUser) {
        return res.status(404).json({
          success: false,
          message: 'User not found',
        });
      }

      // Return a success message with the updated user data
      return res.status(200).json({
        success: true,
        message: 'Multiple login changed successfully',
        Toggle: updatedUser.Toggle,
      });
    } catch (err) {
      console.error('Error updating user toggle value:', err);
      return res.status(500).json({
        success: false,
        message: 'Failed to update user toggle value',
        error: err.message,
      });
    }
  },

  UpdatePromoCode: async (req, res) => {
    try {
      const { promoCode } = req.body;
      const userId = req.user.id; // Ensure req.user is populated correctly

      // Step 1: Check if the promo code already exists in the CompanyandUser table
      const existingPromo = await model.User.findOne({ promoCode }); // Adjusted to match your model

      if (existingPromo) {
        return res.status(400).json({
          success: false,
          message: 'Promo code already in use. Please generate a new one.',
        });
      }

      // Step 2: 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',
        });
      }

      console.log("user.CompanyandUserId:", user.CompanyandUserId);

      // Step 3: Get the CompanyandUserId from the user
      const companyAndUserId = user.CompanyandUserId;
      console.log("companyAndUserId:", companyAndUserId);

      // Step 4: Use CompanyandUserId to find the associated company in the User table
      const company = await model.CompanyandUser.findById(companyAndUserId); // This should be adjusted if the company is a different model

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

      // Step 5: Insert or update the promo code in the CompanyandUser table
      const updatedPromo = await model.User.updateOne(
        { _id: companyAndUserId }, // Assuming you're using _id as the unique identifier
        { $set: { promoCode } }, // Update the promo code
        { upsert: true, new: true } // Options to create if not found
      );

      return res.status(200).json({
        success: true,
        message: 'Promo code updated successfully',
        data: updatedPromo, // Returning the updated document details if needed
      });
    } catch (err) {
      console.error('Error updating promo code:', err);
      return res.status(500).json({
        success: false,
        message: 'Failed to update promo code',
        error: err.message,
      });
    }
  },
  getUser: async (req, res) => {
    try {
      const adminId = req.user.id;

      // Find users where adminId matches req.user.id
      const users = await model.User.find({ AdminId: adminId }).select('name _id');

      // If no users found
      if (!users || users.length === 0) {
        return res.status(404).json({ message: 'No users found for this admin.' });
      }

      // Return user name and id
      res.status(200).json(users);
    } catch (error) {
      console.error('Error fetching users:', error);
      res.status(500).json({ message: 'Server error' });
    }
  }


};

module.exports = adminController;
