import mongoose from "mongoose";
import RetailDistributor from "./RetailDistributorModel.js";
import validator from "validator";
import password from "secure-random-password";
import crypto from "crypto";
import { RdOrder } from "../RD_Ordes/rdOrderModal.js";
import sendEmail, { sendOtp } from "../../Utils/sendEmail.js";
import { KYC } from "../KYC/KycModel.js";
import { generatePassword } from "../../Utils/generatepassword.js";
import XLSX from "xlsx";
import fs from "fs";
import path from "path";

export const uploadRetaildistributors = async (req, res) => {
  try {
    if (!mongoose.Types.ObjectId.isValid(req.user._id)) {
      return res.status(400).json({ message: "Please login again" });
    }
    if (!req.files || !req.files.file) {
      return res.status(400).json({ message: "No file uploaded" });
    }

    const file = req.files.file;
    const filePath = path.join("public", "uploads", file.name);

    // Ensure 'uploads' directory exists
    if (!fs.existsSync(path.dirname(filePath))) {
      fs.mkdirSync(path.dirname(filePath), { recursive: true });
    }

    // Move the file from temp to the uploads directory
    await file.mv(filePath);

    // Process the file
    const fileBuffer = fs.readFileSync(filePath);
    const workbook = XLSX.read(fileBuffer, { type: "buffer" });
    const sheetName = workbook.SheetNames[0];
    const worksheet = workbook.Sheets[sheetName];
    const data = XLSX.utils.sheet_to_json(worksheet, { header: 1 });

    if (data.length <= 1) {
      return res
        .status(400)
        .json({ message: "Empty spreadsheet or no data found" });
    }

    const headers = data[0];

    // Map headers from the Excel file to your schema
    const headerMapping = {
      "Retail Distributor Name": "name",
      Email: "email",
      "Phone Number": "mobile_number",
      "PAN Number": "pan_number",
      "Trade Name": "trade_name",
      "GST Number": "gst_number",
      "Aadhar Number": "aadhar_number",
      State: "state",
      City: "city",
      District: "district",
      Address: "address",
      Pincode: "pincode",
    };

    const requiredHeaders = Object.keys(headerMapping);

    if (!requiredHeaders.every((header) => headers.includes(header))) {
      return res
        .status(400)
        .json({ message: "Missing required columns in spreadsheet" });
    }

    const errors = [];
    const newlyCreated = [];
    const updatedDistributors = [];

    for (let i = 1; i < data.length; i++) {
      const row = data[i];
      const item = {};

      headers.forEach((header, index) => {
        if (headerMapping[header]) {
          item[headerMapping[header]] =
            row[index] !== undefined ? row[index] : "";
        }
      });

      // Initialize error tracking for each item
      const missingFields = new Set();
      const validationErrors = new Set();

      // Validate required fields
      if (!item.name) missingFields.add("name");
      if (!item.email) missingFields.add("email");
      if (!item.mobile_number) missingFields.add("mobile_number");
      if (!item.pan_number) missingFields.add("pan_number");
      if (!item.gst_number) missingFields.add("gst_number");
      if (!item.trade_name) missingFields.add("trade_name");
      if (!item.aadhar_number) missingFields.add("aadhar_number");
      if (!item.state) missingFields.add("state");
      if (!item.city) missingFields.add("city");
      if (!item.pincode) missingFields.add("pincode");
      if (!item.district) missingFields.add("district");
      if (!item.address) missingFields.add("address");

      // Check email validity
      if (item.email && !validator.isEmail(item.email)) {
        validationErrors.add("incorrect mail");
      }

      // Validate mobile number
      if (item.mobile_number && !/^\d{10}$/.test(item.mobile_number)) {
        validationErrors.add("Invalid Mobile Number (should be 10 digits)");
      }

      // Check GST, PAN, and postal code validation
      item.pan_number = item.pan_number ? item.pan_number.toUpperCase() : "";
      item.gst_number = item.gst_number ? item.gst_number.toUpperCase() : "";

      // Validate PAN Number
      if (
        item.pan_number &&
        !/^[A-Z]{5}[0-9]{4}[A-Z]{1}$/.test(item.pan_number)
      ) {
        validationErrors.add("Invalid PAN Number");
      }

      // Validate GST Number
      if (
        item.gst_number &&
        !/^(\d{2}[A-Z]{5}\d{4}[A-Z]{1}\d[Z]{1}[A-Z\d]{1})$/.test(
          item.gst_number
        )
      ) {
        validationErrors.add("Invalid GST Number");
      }
      // Validate Aadhar number
      if (item.aadhar_number && !/^\d{12}$/.test(item.aadhar_number)) {
        validationErrors.add("Invalid Aadhar Number (should be 12 digits)");
      }
      // Validate Postal Code
      if (item.pincode && !/^\d{6}$/.test(item.pincode)) {
        validationErrors.add("Invalid Postal Code");
      }

      // Combine all errors into a single message
      let errorMessage = "";
      if (missingFields.size > 0) {
        errorMessage += `Missing fields: ${Array.from(missingFields).join(
          ", "
        )}. `;
      }
      if (validationErrors.size > 0) {
        errorMessage += `Validation errors: ${Array.from(validationErrors).join(
          ", "
        )}.`;
      }

      // If there are errors, push them to the errors array
      if (errorMessage.trim()) {
        errors.push({
          name: item.name || "N/A",
          email: item.email || "N/A",
          TradeName: item.trade_name || "N/A",
          phone: item.mobile_number || "N/A",
          panNumber: item.pan_number || "N/A",
          gstNumber: item.gst_number || "N/A",
          AadharNumber: item.aadhar_number || "N/A",
          message: errorMessage.trim(),
        });
        continue;
      }

      // Generate a password
      const password = generatePassword(item.name, item.email);

      // Check for existing user by uniqueId
      let Kyc = await KYC.findOne({ email: item.email });
      let Retaildistributor = await RetailDistributor.findOne({
        email: item.email,
      });
      if (Kyc) {
        // Track updated fields
        const updatedFields = [];

        // Check for changes in user details
        let kycUpdated = false;
        for (let field in item) {
          const currentValue = Kyc[field]?.toString();
          const newValue = item[field]?.toString();
        
          if (currentValue !== newValue) {
            updatedFields.push(field);
            Kyc[field] = item[field]; // Update Kyc with the new value
        
            if (Retaildistributor && field !== 'email') {
              Retaildistributor[field] = item[field];
            }
            kycUpdated = true;
          }
        }
        
        // Update Kyc and Retaildistributor if there are any changes
        if (kycUpdated) {
          await Kyc.save();
          await Retaildistributor.save();
          updatedDistributors.push({
            ...Kyc._doc,
            updatedFields: updatedFields.join(", "),
          });
        }
      } else {
        // Create a new Kyc
        Kyc = new KYC({
          ...item,
          status: "approved",
        });
        const newkyc = await Kyc.save();
        const retailDistributorData = {
          name: item.name,
          email: item.email,
          mobile_number: item.mobile_number,
          kyc: newkyc._id,
          password,
        };
        Retaildistributor = new RetailDistributor(retailDistributorData);
        await Retaildistributor.save();
        // Send email with the new password
        await sendEmail({
          to: `${item.email}`, // Change to your recipient
          from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
          subject: `Cheminova Account Created`,
          html: `Your Retail Distributor Account is created successfully.
          <br/>name is: <strong>${item.name}</strong>
          <br/>
          <br/>MobileNumber is: <strong>${item.mobile_number}</strong><br/>
          <br/>Email is: <strong>${item.email}</strong><br/>
          <br/>password is: <strong>${password}</strong><br/><br/>If you have not requested this email, please ignore it.`,
        });
        newlyCreated.push({ Kyc });
      }
    }

    res.status(200).json({
      message: "File processed successfully",
      newlyCreated,
      updatedDistributors,
      errors,
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Internal Server Error" });
  }
};

export const loginRD = async (req, res) => {
  const { email, password } = req.body;

  try {
    if (!email || !password) {
      return res.status(400).json({ message: "Please Enter Email & Password" });
    }

    const retailDistributor = await RetailDistributor.findOne({ email }).select(
      "+password"
    );

    if (!retailDistributor) {
      return res.status(400).json({ message: "Invalid Email or Password" });
    }

    const isPasswordMatched = await retailDistributor.comparePassword(password);

    if (!isPasswordMatched) {
      return res.status(400).json({ message: "Invalid Email or Password" });
    }
    const token = retailDistributor.getJWTToken();

    return res.status(200).json({
      success: true,
      token,
      message: "Login Successfully",
    });
  } catch (error) {
    return res.status(500).json({
      message: error.message ? error.message : "Something went wrong!",
    });
  }
};

export const ChangePasswordRD = async (req, res) => {
  // Retrieve id from req.params
  const { oldPassword, newPassword, confirmPassword } = req.body;
  const userId = req.user._id; // Use the ID from the URL or from the authenticated user
  // console.log(userId);
  if (!oldPassword) {
    return res.status(400).json({ message: "Please Enter Old password" });
  }
  if (!newPassword) {
    return res.status(400).json({ message: "Please Enter New Password " });
  }
  if (!confirmPassword) {
    return res.status(400).json({ message: "Please Enter Confirm Password" });
  }
  try {
    const retailDistributor = await RetailDistributor.findById(userId).select(
      "+password"
    );

    if (!retailDistributor) {
      return res.status(404).json({ message: "Retail Distributer not found" });
    }

    const isPasswordMatched = await retailDistributor.comparePassword(
      oldPassword
    );

    if (!isPasswordMatched) {
      return res.status(400).json({ message: "Old password is incorrect" });
    }

    if (newPassword !== confirmPassword) {
      return res
        .status(400)
        .json({ message: "New password and confirm Password do not match" });
    }

    retailDistributor.password = newPassword;
    await retailDistributor.save();

    return res
      .status(200)
      .json({ success: true, message: "Password updated successfully" });
  } catch (error) {
    console.error("Error updating password:", error);
    return res.status(500).json({
      message: error.message ? error.message : "Server error!",
    });
  }
};

export const forgotPasswordRD = async (req, res) => {
  try {
    // Check if email is provided
    const { email } = req.body;
    if (!email) {
      return res.status(400).json({ message: "Please Enter Email!" });
    }

    // Find the Retail Distributor by email
    const retailDistributor = await RetailDistributor.findOne({ email });
    if (!retailDistributor) {
      return res.status(404).json({ message: "Retail Distributor not found" });
    }

    // Generate a random password
    const newPassword = password.randomPassword({
      length: 12,
      characters: [
        { characters: password.upper, exactly: 1 }, // At least 1 uppercase letter
        { characters: password.symbols, exactly: 1 }, // At least 1 symbol
        password.lower, // Lowercase letters
        password.digits, // Digits
      ],
    });

    // Update the retail distributor's password
    retailDistributor.password = newPassword;
    await retailDistributor.save(); // The pre-save hook in your schema will handle password hashing

    // Send an email to the retail distributor with the new password
    await sendEmail({
      to: retailDistributor.email,
      from: process.env.SEND_EMAIL_FROM,
      subject: `Cheminova Password Recovery`,
      html: `Your new password is: <strong>${newPassword}</strong><br/><br/>If you did not request this, please ignore this email.`,
    });

    // Respond with success message
    return res.status(200).json({
      success: true,
      message: `Email sent to ${retailDistributor.email} successfully`,
    });
  } catch (error) {
    console.error("Error during password reset:", error);
    return res.status(500).json({
      message: error.message || "Something went wrong!",
    });
  }
};

export const UpdateProfileRD = async (req, res) => {
  const { name, mobile_number } = req.body; // Only expecting name from the request body

  const userId = req.user._id; // User ID from authenticated user

  try {
    // Find the RetailDistributor by user ID
    const retailDistributor = await RetailDistributor.findById(userId);

    if (!retailDistributor) {
      return res.status(404).json({ message: "Retail Distributor not found" });
    }

    // Assuming you have an 'isVerified' field in your RetailDistributor schema

    // Update name if provided
    if (name) {
      retailDistributor.name = name;
      retailDistributor.mobile_number = mobile_number
        ? mobile_number
        : retailDistributor.mobile_number;
    } else {
      return res.status(400).json({ message: "Name is required" });
    }

    // Save the updated RetailDistributor
    await retailDistributor.save();

    return res.status(200).json({
      retailDistributor,
      message: "Profile updated successfully",
    });
  } catch (error) {
    return res.status(500).json({
      message: error.message || "Server error!",
    });
  }
};

export const getmyProfileRD = async (req, res) => {
  try {
    // Fetch the profile data using the authenticated user's ID
    const myData = await RetailDistributor.findById(req.user?._id);

    if (myData) {
      return res.status(200).json({
        success: true,
        message: "Profile fetched successfully!",
        myData,
      });
    } else {
      return res.status(404).json({
        success: false,
        message: "Retail Distributor not found",
      });
    }
  } catch (error) {
    return res.status(500).json({
      success: false,
      message: error.message || "Something went wrong!",
    });
  }
};

//reatil distributor mapping
export const getAllRetailDistributorApproved = async (req, res) => {
  try {
    // Extract query parameters
    const {
      page = 1,
      show = 10,
      tradename,
      name,
      mobile_number,
      principaldistributor,
    } = req.query;
    const skip = (page - 1) * show;

    // Build the aggregation pipeline
    let pipeline = [
      {
        $lookup: {
          from: "kycs", // Assuming your KYC collection is named "kycs"
          localField: "kyc",
          foreignField: "_id",
          as: "kycDetails",
        },
      },
      { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays
      {
        $lookup: {
          from: "users", // Assuming your User collection is named "users"
          localField: "principal_distributer",
          foreignField: "_id",
          as: "principalDetails",
        },
      },
      {
        $unwind: {
          path: "$principalDetails",
          preserveNullAndEmptyArrays: true,
        },
      }, // Unwind principalDetails and allow null/empty arrays

      // Lookup for mappedTM (Territory Manager)
      {
        $lookup: {
          from: "territorymanagers", // Assuming your Territory Manager collection
          localField: "mappedTM",
          foreignField: "_id",
          as: "mappedTMDetails",
        },
      },
      {
        $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true },
      }, // Unwind mappedTMDetails and allow null/empty arrays

      // Lookup for mappedSC (Sales Coordinator)
      {
        $lookup: {
          from: "salescoordinators", // Assuming your Sales Coordinator collection
          localField: "mappedSC",
          foreignField: "_id",
          as: "mappedSCDetails",
        },
      },
      {
        $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true },
      }, // Unwind mappedSCDetails and allow null/empty arrays

      // Filter to ensure data exists in kyc or principalDetails
      {
        $match: {
          $or: [
            { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists
            { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists
          ],
        },
      },
    ];

    // Add filters based on query parameters

    // Filter by KYC trade_name (case-insensitive)
    if (tradename) {
      pipeline.push({
        $match: { "kycDetails.trade_name": new RegExp(tradename, "i") },
      });
    }

    // Filter by principal_distributer name (case-insensitive)
    if (principaldistributor) {
      pipeline.push({
        $match: {
          "principalDetails.name": new RegExp(principaldistributor, "i"),
        },
      });
    }

    // Filter by name (RetailDistributor model's name)
    if (name) {
      pipeline.push({
        $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name
      });
    }

    // Filter by mobile_number (RetailDistributor model's mobile number)
    if (mobile_number) {
      pipeline.push({
        $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number
      });
    }

    // Project only the required fields
    pipeline.push({
      $project: {
        _id: 1, // RetailDistributor ID
        uniqueId: 1, // RetailDistributor uniqueId
        name: 1, // RetailDistributor name
        mobile_number: 1, // RetailDistributor mobile_number
        email: 1, // RetailDistributor email
        "kycDetails.trade_name": 1, // Only trade_name from kyc
        "principalDetails.name": 1, // Only name from principal_distributer
        "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager)
        "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator)
        createdAt: 1, // For sorting
      },
    });

    // Pagination and sorting
    pipeline.push({ $sort: { createdAt: -1 } });
    pipeline.push({ $skip: skip });
    pipeline.push({ $limit: parseInt(show) });

    // Execute the aggregation pipeline
    const Retaildistributor = await RetailDistributor.aggregate(pipeline);

    // Get total count of documents matching the query
    const countPipeline = [
      {
        $lookup: {
          from: "kycs",
          localField: "kyc",
          foreignField: "_id",
          as: "kycDetails",
        },
      },
      { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } },
      {
        $lookup: {
          from: "users",
          localField: "principal_distributer",
          foreignField: "_id",
          as: "principalDetails",
        },
      },
      {
        $unwind: {
          path: "$principalDetails",
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $match: {
          $or: [
            { "kycDetails.trade_name": { $exists: true } },
            { "principalDetails.name": { $exists: true } },
          ],
        },
      },
    ];

    // Apply search filters to count query

    // Filter by KYC trade_name
    if (tradename) {
      countPipeline.push({
        $match: { "kycDetails.trade_name": new RegExp(tradename, "i") },
      });
    }

    // Filter by principal_distributer name
    if (principaldistributor) {
      countPipeline.push({
        $match: {
          "principalDetails.name": new RegExp(principaldistributor, "i"),
        },
      });
    }

    // Filter by name
    if (name) {
      countPipeline.push({
        $match: { name: new RegExp(name, "i") },
      });
    }

    // Filter by mobile_number
    if (mobile_number) {
      countPipeline.push({
        $match: { mobile_number: new RegExp(mobile_number, "i") },
      });
    }

    // Get the total count of filtered documents
    const total_data = await RetailDistributor.aggregate([
      ...countPipeline,
      { $count: "total" },
    ]);

    const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found

    // Send the response with pagination data
    res.status(200).json({
      success: true,
      total_data: totalCount,
      total_pages: Math.ceil(totalCount / show),
      Retaildistributor,
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Server Error", error });
  }
};
export const getAllRetailDistributorwithTotalorder = async (req, res) => {
  try {
    const {
      page = 1,
      show = 10,
      tradename,
      name,
      mobile_number,
      principaldistributor,
    } = req.query;
    const skip = (page - 1) * show;

    // Build the aggregation pipeline
    let pipeline = [
      {
        $lookup: {
          from: "kycs", // KYC collection
          localField: "kyc",
          foreignField: "_id",
          as: "kycDetails",
        },
      },
      { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } },
      {
        $lookup: {
          from: "users", // Principal Distributor collection
          localField: "principal_distributer",
          foreignField: "_id",
          as: "principalDetails",
        },
      },
      {
        $unwind: {
          path: "$principalDetails",
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $lookup: {
          from: "territorymanagers", // Territory Manager collection
          localField: "mappedTM",
          foreignField: "_id",
          as: "mappedTMDetails",
        },
      },
      {
        $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true },
      },
      {
        $lookup: {
          from: "salescoordinators", // Sales Coordinator collection
          localField: "mappedSC",
          foreignField: "_id",
          as: "mappedSCDetails",
        },
      },
      {
        $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true },
      },
    ];

    // Add filters based on query parameters
    const matchConditions = {};
    if (tradename)
      matchConditions["kycDetails.trade_name"] = new RegExp(tradename, "i");
    if (name) matchConditions["name"] = new RegExp(name, "i");
    if (mobile_number)
      matchConditions["mobile_number"] = new RegExp(mobile_number, "i");
    if (principaldistributor)
      matchConditions["principalDetails.name"] = new RegExp(
        principaldistributor,
        "i"
      );

    if (Object.keys(matchConditions).length) {
      pipeline.push({ $match: matchConditions });
    }

    // Project required fields early
    pipeline.push({
      $project: {
        _id: 1,
        uniqueId: 1,
        name: 1,
        mobile_number: 1,
        email: 1,
        "kycDetails.trade_name": 1,
        "principalDetails.name": 1,
        "mappedTMDetails.name": 1,
        "mappedSCDetails.name": 1,
        createdAt: 1,
      },
    });

    // Pagination and sorting
    pipeline.push({ $sort: { createdAt: -1 } });
    pipeline.push({ $skip: skip });
    pipeline.push({ $limit: parseInt(show) });

    // Execute the main aggregation pipeline
    const Retaildistributor = await RetailDistributor.aggregate(pipeline);

    // Aggregate orders data for each distributor
    const orderStats = await RdOrder.aggregate([
      {
        $match: { addedBy: { $in: Retaildistributor.map((user) => user._id) } },
      },
      {
        $group: {
          _id: "$addedBy", // Group by distributor ID
          totalOrders: { $sum: 1 }, // Count total orders
          lastOrderDate: { $max: "$createdAt" }, // Get last order date
        },
      },
    ]);

    // Combine order stats with Retaildistributor data
    const usersWithOrderStats = Retaildistributor.map((user) => {
      const orderData = orderStats.find(
        (order) => order._id.toString() === user._id.toString()
      );
      return {
        ...user,
        totalOrders: orderData ? orderData.totalOrders : 0,
        lastOrderDate: orderData ? orderData.lastOrderDate : null,
      };
    });

    // Get total count of documents matching the query
    const countPipeline = [{ $match: matchConditions }, { $count: "total" }];
    const total_data = await RetailDistributor.aggregate(countPipeline);
    const totalCount = total_data[0]?.total || 0;

    // Send the response
    res.status(200).json({
      success: true,
      total_data: totalCount,
      total_pages: Math.ceil(totalCount / show),
      Retaildistributor: usersWithOrderStats,
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Server Error", error });
  }
};

//get RD by Id
export const getRDId = async (req, res) => {
  try {
    const { id } = req.params;
    // console.log(id);
    // Fetch the KYC document from the database by ID
    const RD = await RetailDistributor.findById(id)
      .populate("principal_distributer", "name email phone")
      .populate("addedBy")
      .populate("kyc")
      .populate("mappedTM")
      .populate("mappedSC");

    // Check if the KYC document exists
    if (!RD) {
      return res.status(404).json({ message: "No RetailDistributor found" });
    }
    // console.log(RD);
    // Send the fetched KYC document as a response
    res.status(200).json(RD);
  } catch (error) {
    // Handle any errors that occur during the fetch operation
    res.status(500).json({ message: "Server Error", error });
  }
};
//mapping

export const getAllRDbytmid = async (req, res) => {
  try {
    // Extract query parameters
    const {
      page = 1,
      show = 10,
      tradename,
      name,
      mobile_number,
      principaldistributor,
    } = req.query;
    const { mappedTMId } = req.params; // Extract mappedTM ID from request params

    // Convert mappedTMId to ObjectId if it's a valid ObjectId string
    let mappedTMObjectId;
    try {
      mappedTMObjectId = mongoose.Types.ObjectId(mappedTMId);
    } catch (error) {
      return res.status(400).json({ message: "Invalid mappedTM ID format" });
    }

    const skip = (page - 1) * show;

    // Build the aggregation pipeline
    let pipeline = [
      {
        $match: {
          mappedTM: mappedTMObjectId, // Filter by mappedTM ObjectId
        },
      },
      {
        $lookup: {
          from: "kycs", // Assuming your KYC collection is named "kycs"
          localField: "kyc",
          foreignField: "_id",
          as: "kycDetails",
        },
      },
      { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays
      {
        $lookup: {
          from: "users", // Assuming your User collection is named "users"
          localField: "principal_distributer",
          foreignField: "_id",
          as: "principalDetails",
        },
      },
      {
        $unwind: {
          path: "$principalDetails",
          preserveNullAndEmptyArrays: true,
        },
      }, // Unwind principalDetails and allow null/empty arrays

      // Lookup for mappedTM (Territory Manager)
      {
        $lookup: {
          from: "territorymanagers", // Assuming your Territory Manager collection
          localField: "mappedTM",
          foreignField: "_id",
          as: "mappedTMDetails",
        },
      },
      {
        $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true },
      }, // Unwind mappedTMDetails and allow null/empty arrays

      // Lookup for mappedSC (Sales Coordinator)
      {
        $lookup: {
          from: "salescoordinators", // Assuming your Sales Coordinator collection
          localField: "mappedSC",
          foreignField: "_id",
          as: "mappedSCDetails",
        },
      },
      {
        $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true },
      }, // Unwind mappedSCDetails and allow null/empty arrays

      // Filter to ensure data exists in kyc or principalDetails
      {
        $match: {
          $or: [
            { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists
            { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists
          ],
        },
      },
    ];

    // Add filters based on query parameters

    // Filter by KYC trade_name (case-insensitive)
    if (tradename) {
      pipeline.push({
        $match: { "kycDetails.trade_name": new RegExp(tradename, "i") },
      });
    }

    // Filter by principal_distributer name (case-insensitive)
    if (principaldistributor) {
      pipeline.push({
        $match: {
          "principalDetails.name": new RegExp(principaldistributor, "i"),
        },
      });
    }

    // Filter by name (RetailDistributor model's name)
    if (name) {
      pipeline.push({
        $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name
      });
    }

    // Filter by mobile_number (RetailDistributor model's mobile number)
    if (mobile_number) {
      pipeline.push({
        $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number
      });
    }

    // Project only the required fields
    pipeline.push({
      $project: {
        _id: 1, // RetailDistributor ID
        uniqueId: 1, // RetailDistributor uniqueId
        name: 1, // RetailDistributor name
        mobile_number: 1, // RetailDistributor mobile_number
        email: 1, // RetailDistributor email
        "kycDetails.trade_name": 1, // Only trade_name from kyc
        "principalDetails.name": 1, // Only name from principal_distributer
        "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager)
        "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator)
        createdAt: 1, // For sorting
      },
    });

    // Pagination and sorting
    pipeline.push({ $sort: { createdAt: -1 } });
    pipeline.push({ $skip: skip });
    pipeline.push({ $limit: parseInt(show) });

    // Execute the aggregation pipeline
    const Retaildistributor = await RetailDistributor.aggregate(pipeline);

    // Get total count of documents matching the query
    const countPipeline = [
      {
        $match: {
          mappedTM: mappedTMObjectId, // Filter by mappedTM ObjectId
        },
      },
      {
        $lookup: {
          from: "kycs",
          localField: "kyc",
          foreignField: "_id",
          as: "kycDetails",
        },
      },
      { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } },
      {
        $lookup: {
          from: "users",
          localField: "principal_distributer",
          foreignField: "_id",
          as: "principalDetails",
        },
      },
      {
        $unwind: {
          path: "$principalDetails",
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $match: {
          $or: [
            { "kycDetails.trade_name": { $exists: true } },
            { "principalDetails.name": { $exists: true } },
          ],
        },
      },
    ];

    // Apply search filters to count query

    // Filter by KYC trade_name
    if (tradename) {
      countPipeline.push({
        $match: { "kycDetails.trade_name": new RegExp(tradename, "i") },
      });
    }

    // Filter by principal_distributer name
    if (principaldistributor) {
      countPipeline.push({
        $match: {
          "principalDetails.name": new RegExp(principaldistributor, "i"),
        },
      });
    }

    // Filter by name
    if (name) {
      countPipeline.push({
        $match: { name: new RegExp(name, "i") },
      });
    }

    // Filter by mobile_number
    if (mobile_number) {
      countPipeline.push({
        $match: { mobile_number: new RegExp(mobile_number, "i") },
      });
    }

    // Get the total count of filtered documents
    const total_data = await RetailDistributor.aggregate([
      ...countPipeline,
      { $count: "total" },
    ]);

    const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found

    // Send the response with pagination data
    res.status(200).json({
      success: true,
      total_data: totalCount,
      total_pages: Math.ceil(totalCount / show),
      Retaildistributor,
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Server Error", error });
  }
};
export const getAllRDbyscid = async (req, res) => {
  try {
    // Extract query parameters
    const {
      page = 1,
      show = 10,
      tradename,
      name,
      mobile_number,
      principaldistributor,
    } = req.query;
    const { mappedSCId } = req.params; // Extract mappedTM ID from request params

    // Convert mappedSCId to ObjectId if it's a valid ObjectId string
    let mappedSCObjectId;
    try {
      mappedSCObjectId = mongoose.Types.ObjectId(mappedSCId);
    } catch (error) {
      return res.status(400).json({ message: "Invalid mappedSC ID format" });
    }

    const skip = (page - 1) * show;

    // Build the aggregation pipeline
    let pipeline = [
      {
        $match: {
          mappedSC: mappedSCObjectId, // Filter by mappedSC ObjectId
        },
      },
      {
        $lookup: {
          from: "kycs", // Assuming your KYC collection is named "kycs"
          localField: "kyc",
          foreignField: "_id",
          as: "kycDetails",
        },
      },
      { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays
      {
        $lookup: {
          from: "users", // Assuming your User collection is named "users"
          localField: "principal_distributer",
          foreignField: "_id",
          as: "principalDetails",
        },
      },
      {
        $unwind: {
          path: "$principalDetails",
          preserveNullAndEmptyArrays: true,
        },
      }, // Unwind principalDetails and allow null/empty arrays

      // Lookup for mappedTM (Territory Manager)
      {
        $lookup: {
          from: "territorymanagers", // Assuming your Territory Manager collection
          localField: "mappedTM",
          foreignField: "_id",
          as: "mappedTMDetails",
        },
      },
      {
        $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true },
      }, // Unwind mappedTMDetails and allow null/empty arrays

      // Lookup for mappedSC (Sales Coordinator)
      {
        $lookup: {
          from: "salescoordinators", // Assuming your Sales Coordinator collection
          localField: "mappedSC",
          foreignField: "_id",
          as: "mappedSCDetails",
        },
      },
      {
        $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true },
      }, // Unwind mappedSCDetails and allow null/empty arrays

      // Filter to ensure data exists in kyc or principalDetails
      {
        $match: {
          $or: [
            { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists
            { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists
          ],
        },
      },
    ];

    // Add filters based on query parameters

    // Filter by KYC trade_name (case-insensitive)
    if (tradename) {
      pipeline.push({
        $match: { "kycDetails.trade_name": new RegExp(tradename, "i") },
      });
    }

    // Filter by principal_distributer name (case-insensitive)
    if (principaldistributor) {
      pipeline.push({
        $match: {
          "principalDetails.name": new RegExp(principaldistributor, "i"),
        },
      });
    }

    // Filter by name (RetailDistributor model's name)
    if (name) {
      pipeline.push({
        $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name
      });
    }

    // Filter by mobile_number (RetailDistributor model's mobile number)
    if (mobile_number) {
      pipeline.push({
        $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number
      });
    }

    // Project only the required fields
    pipeline.push({
      $project: {
        _id: 1, // RetailDistributor ID
        uniqueId: 1, // RetailDistributor uniqueId
        name: 1, // RetailDistributor name
        mobile_number: 1, // RetailDistributor mobile_number
        email: 1, // RetailDistributor email
        "kycDetails.trade_name": 1, // Only trade_name from kyc
        "principalDetails.name": 1, // Only name from principal_distributer
        "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager)
        "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator)
        createdAt: 1, // For sorting
      },
    });

    // Pagination and sorting
    pipeline.push({ $sort: { createdAt: -1 } });
    pipeline.push({ $skip: skip });
    pipeline.push({ $limit: parseInt(show) });

    // Execute the aggregation pipeline
    const Retaildistributor = await RetailDistributor.aggregate(pipeline);

    // Get total count of documents matching the query
    const countPipeline = [
      {
        $match: {
          mappedSC: mappedSCObjectId, // Filter by mappedTM ObjectId
        },
      },
      {
        $lookup: {
          from: "kycs",
          localField: "kyc",
          foreignField: "_id",
          as: "kycDetails",
        },
      },
      { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } },
      {
        $lookup: {
          from: "users",
          localField: "principal_distributer",
          foreignField: "_id",
          as: "principalDetails",
        },
      },
      {
        $unwind: {
          path: "$principalDetails",
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $match: {
          $or: [
            { "kycDetails.trade_name": { $exists: true } },
            { "principalDetails.name": { $exists: true } },
          ],
        },
      },
    ];

    // Apply search filters to count query

    // Filter by KYC trade_name
    if (tradename) {
      countPipeline.push({
        $match: { "kycDetails.trade_name": new RegExp(tradename, "i") },
      });
    }

    // Filter by principal_distributer name
    if (principaldistributor) {
      countPipeline.push({
        $match: {
          "principalDetails.name": new RegExp(principaldistributor, "i"),
        },
      });
    }

    // Filter by name
    if (name) {
      countPipeline.push({
        $match: { name: new RegExp(name, "i") },
      });
    }

    // Filter by mobile_number
    if (mobile_number) {
      countPipeline.push({
        $match: { mobile_number: new RegExp(mobile_number, "i") },
      });
    }

    // Get the total count of filtered documents
    const total_data = await RetailDistributor.aggregate([
      ...countPipeline,
      { $count: "total" },
    ]);

    const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found

    // Send the response with pagination data
    res.status(200).json({
      success: true,
      total_data: totalCount,
      total_pages: Math.ceil(totalCount / show),
      Retaildistributor,
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Server Error", error });
  }
};
export const getAllRDbypdid = async (req, res) => {
  try {
    // Extract query parameters
    const { page = 1, show = 10, tradename, name, mobile_number } = req.query;
    const { mappedPDId } = req.params; // Extract mappedTM ID from request params

    // Convert mappedPDId to ObjectId if it's a valid ObjectId string
    let mappedPDObjectId;
    try {
      mappedPDObjectId = mongoose.Types.ObjectId(mappedPDId);
    } catch (error) {
      return res.status(400).json({ message: "Invalid mappedPD ID format" });
    }

    const skip = (page - 1) * show;

    // Build the aggregation pipeline
    let pipeline = [
      {
        $match: {
          principal_distributer: mappedPDObjectId, // Filter by principal_distributer ObjectId
        },
      },
      {
        $lookup: {
          from: "kycs", // Assuming your KYC collection is named "kycs"
          localField: "kyc",
          foreignField: "_id",
          as: "kycDetails",
        },
      },
      { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } }, // Unwind kycDetails and allow null/empty arrays
      {
        $lookup: {
          from: "users", // Assuming your User collection is named "users"
          localField: "principal_distributer",
          foreignField: "_id",
          as: "principalDetails",
        },
      },
      {
        $unwind: {
          path: "$principalDetails",
          preserveNullAndEmptyArrays: true,
        },
      }, // Unwind principalDetails and allow null/empty arrays

      // Lookup for mappedTM (Territory Manager)
      {
        $lookup: {
          from: "territorymanagers", // Assuming your Territory Manager collection
          localField: "mappedTM",
          foreignField: "_id",
          as: "mappedTMDetails",
        },
      },
      {
        $unwind: { path: "$mappedTMDetails", preserveNullAndEmptyArrays: true },
      }, // Unwind mappedTMDetails and allow null/empty arrays

      // Lookup for mappedSC (Sales Coordinator)
      {
        $lookup: {
          from: "salescoordinators", // Assuming your Sales Coordinator collection
          localField: "mappedSC",
          foreignField: "_id",
          as: "mappedSCDetails",
        },
      },
      {
        $unwind: { path: "$mappedSCDetails", preserveNullAndEmptyArrays: true },
      }, // Unwind mappedSCDetails and allow null/empty arrays

      // Filter to ensure data exists in kyc or principalDetails
      {
        $match: {
          $or: [
            { "kycDetails.trade_name": { $exists: true } }, // Ensure KYC exists
            { "principalDetails.name": { $exists: true } }, // Ensure Principal Distributor exists
          ],
        },
      },
    ];

    // Add filters based on query parameters

    // Filter by KYC trade_name (case-insensitive)
    if (tradename) {
      pipeline.push({
        $match: { "kycDetails.trade_name": new RegExp(tradename, "i") },
      });
    }

    // Filter by name (RetailDistributor model's name)
    if (name) {
      pipeline.push({
        $match: { name: new RegExp(name, "i") }, // Case-insensitive search for name
      });
    }

    // Filter by mobile_number (RetailDistributor model's mobile number)
    if (mobile_number) {
      pipeline.push({
        $match: { mobile_number: new RegExp(mobile_number, "i") }, // Case-insensitive search for mobile_number
      });
    }

    // Project only the required fields
    pipeline.push({
      $project: {
        _id: 1, // RetailDistributor ID
        uniqueId: 1, // RetailDistributor uniqueId
        name: 1, // RetailDistributor name
        mobile_number: 1, // RetailDistributor mobile_number
        email: 1, // RetailDistributor email
        "kycDetails.trade_name": 1, // Only trade_name from kyc
        "mappedTMDetails.name": 1, // Only name from mappedTM (Territory Manager)
        "mappedSCDetails.name": 1, // Only name from mappedSC (Sales Coordinator)
        "principalDetails.name": 1, // Only name from principal_distributer
        createdAt: 1, // For sorting
      },
    });

    // Pagination and sorting
    pipeline.push({ $sort: { createdAt: -1 } });
    pipeline.push({ $skip: skip });
    pipeline.push({ $limit: parseInt(show) });

    // Execute the aggregation pipeline
    const Retaildistributor = await RetailDistributor.aggregate(pipeline);

    // Get total count of documents matching the query
    const countPipeline = [
      {
        $match: {
          principal_distributer: mappedPDObjectId, // Filter by mappedTM ObjectId
        },
      },
      {
        $lookup: {
          from: "kycs",
          localField: "kyc",
          foreignField: "_id",
          as: "kycDetails",
        },
      },
      { $unwind: { path: "$kycDetails", preserveNullAndEmptyArrays: true } },
      {
        $lookup: {
          from: "users",
          localField: "principal_distributer",
          foreignField: "_id",
          as: "principalDetails",
        },
      },
      {
        $unwind: {
          path: "$principalDetails",
          preserveNullAndEmptyArrays: true,
        },
      },
      {
        $match: {
          $or: [
            { "kycDetails.trade_name": { $exists: true } },
            { "principalDetails.name": { $exists: true } },
          ],
        },
      },
    ];

    // Apply search filters to count query

    // Filter by KYC trade_name
    if (tradename) {
      countPipeline.push({
        $match: { "kycDetails.trade_name": new RegExp(tradename, "i") },
      });
    }

    // Filter by name
    if (name) {
      countPipeline.push({
        $match: { name: new RegExp(name, "i") },
      });
    }

    // Filter by mobile_number
    if (mobile_number) {
      countPipeline.push({
        $match: { mobile_number: new RegExp(mobile_number, "i") },
      });
    }

    // Get the total count of filtered documents
    const total_data = await RetailDistributor.aggregate([
      ...countPipeline,
      { $count: "total" },
    ]);

    const totalCount = total_data[0]?.total || 0; // Ensure count is zero if no data found

    // Send the response with pagination data
    res.status(200).json({
      success: true,
      total_data: totalCount,
      total_pages: Math.ceil(totalCount / show),
      Retaildistributor,
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Server Error", error });
  }
};

export const updateRDMapped = async (req, res) => {
  try {
    const { id } = req.params;
    const { principal_distributor, mappedTM, mappedSC } = req.body;
    // console.log(principal_distributor);
    // Find the RetailDistributor document by ID
    const RD = await RetailDistributor.findById(id);

    if (!RD) {
      return res.status(404).json({ message: "RetailDistributor not found" });
    }

    // Update the fields if provided in the request body
    if (principal_distributor) {
      RD.principal_distributer = principal_distributor;
    }
    if (mappedTM) {
      RD.mappedTM = mappedTM;
    }
    if (mappedSC) {
      RD.mappedSC = mappedSC;
    }

    // Save the updated document
    await RD.save();

    res.status(200).json({
      message: "RetailDistributor record updated successfully",
      data: RD,
    });
  } catch (error) {
    // Handle any errors during the update
    res.status(500).json({
      message: "Error updating RD record",
      error: error.message,
    });
  }
};
export const updateunmapRD = async (req, res) => {
  try {
    const { id } = req.params;
    const { principal_distributor, mappedTM, mappedSC } = req.body;

    // Find the RetailDistributor document by ID
    const RD = await RetailDistributor.findById(id);

    if (!RD) {
      return res.status(404).json({ message: "RetailDistributor not found" });
    }

    // Update the fields if provided in the request body
    if (principal_distributor) {
      RD.principal_distributer = null;
    }
    if (mappedTM) {
      RD.mappedTM = null;
    }
    if (mappedSC) {
      RD.mappedSC = null;
    }
    // Save the updated document
    await RD.save();

    res.status(200).json({
      message: "RetailDistributor record updated successfully",
      data: RD,
    });
  } catch (error) {
    // Handle any errors during the update
    res.status(500).json({
      message: "Error updating RD record",
      error: error.message,
    });
  }
};

export const saveFCMTokenForRD = async (req, res) => {
  const { fcmToken } = req.body;
  const userId = req.user._id;

  try {
    // Fetch the current FCM token for the user
    const user = await RetailDistributor.findById(userId);

    if (!user) {
      return res.status(404).send("User not found");
    }

    // Check if the new FCM token is different from the current one
    if (user.fcm_token && user.fcm_token === fcmToken) {
      return res.status(200).send("FCM Token is already up to date");
    }

    // Update the FCM token
    user.fcm_token = fcmToken;
    await user.save();

    res.status(200).send("FCM Token saved successfully");
  } catch (error) {
    console.error("Error saving FCM Token:", error);
    res.status(500).send("Internal Server Error");
  }
};
