// import hashPassword from '../utils/hashPassword';
import crypto from "crypto";
import mongoose from "mongoose";
import TerritoryManager from "./TerritoryManagerModel.js";
import sendEmail, { sendOtp } from "../../Utils/sendEmail.js";
import validator from "validator";
import password from "secure-random-password";
import catchAsyncErrors from "../../middlewares/catchAsyncErrors.js";
import { generatePassword } from "../../Utils/generatepassword.js";
import XLSX from "xlsx";
import fs from "fs";
import path from "path";
export const uploadTerritoryManagers = 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 = {
      "Territory Manager Name": "name",
      Email: "email",
      "Phone Number": "mobileNumber",
    };

    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 updatedtrritoryManagers = [];

    for (let i = 1; i < data.length; i++) {
      const row = data[i];
      // Skip the row if it's completely empty
      if (row.every((cell) => cell === undefined || cell === "")) {
        continue;
      }
      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.mobileNumber) missingFields.add("mobileNumber");

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

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

      // 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",
          phone: item.mobileNumber || "N/A",
          message: errorMessage.trim(),
        });
        continue;
      }

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

      // Check for existing user by uniqueId
      let territoryManager = await TerritoryManager.findOne({
        email: item.email,
      });

      if (territoryManager) {
        // Track updated fields
        const updatedFields = [];

        // Check for changes in user details
        let territoryManagerUpdated = false;
        for (let field in item) {
          const currentValue = territoryManager[field]?.toString();
          const newValue = item[field]?.toString();

          if (currentValue !== newValue) {
            updatedFields.push(field);
            territoryManager[field] = item[field];
            territoryManagerUpdated = true;
          }
        }

        if (territoryManagerUpdated) {
          await territoryManager.save();
          updatedtrritoryManagers.push({
            ...territoryManager._doc,
            updatedFields: updatedFields.join(", "),
          });
        }
      } else {
        // Create a new territoryManager
        territoryManager = new TerritoryManager({
          ...item,
          password,
          isVerified: true,
        });
        await territoryManager.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 Territory Manager Account is created successfully.
      <br/>name is: <strong>${item?.name}</strong><br/>
      <br/>MobileNumber is: <strong>${item?.mobileNumber}</strong><br/>
      <br/>password is: <strong>${password}</strong><br/><br/>If you have not requested this email, please ignore it.`,
        });
        newlyCreated.push({ territoryManager });
      }
    }

    res.status(200).json({
      message: "File processed successfully",
      newlyCreated,
      updatedtrritoryManagers,
      errors,
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Internal Server Error" });
  }
};
export const register = async (req, res) => {
  let { name, email, countryCode, mobileNumber } = req.body;
  countryCode = countryCode?.trim();
  mobileNumber = mobileNumber?.trim();
  const fullMobileNumber = `${countryCode}${mobileNumber}`;

  try {
    let territoryManager = await TerritoryManager.findOne({
      mobileNumber: fullMobileNumber,
    });

    if (territoryManager && territoryManager.isVerified) {
      return res.status(400).json({
        message:
          "TerritoryManager already registered and verified for this mobile number.",
      });
    }
    // const otp = crypto.randomInt(100000, 1000000).toString();
    const otp = "123456";
    const otpExpires = Date.now() + 1 * 60 * 1000;

    if (territoryManager) {
      territoryManager.otp = otp;
      territoryManager.otpExpires = otpExpires;
    } else {
      territoryManager = new TerritoryManager({
        name,
        email,
        mobileNumber: fullMobileNumber,
        otp,
        otpExpires,
      });
    }
    // Generate uniqueId if not already present
    if (!territoryManager.uniqueId) {
      const currentYear = new Date().getFullYear().toString().slice(-2);
      const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase();
      territoryManager.uniqueId = `${currentYear}-${randomChars}`;
    }
    await territoryManager.save();
    // await sendOtp(
    //   fullMobileNumber,
    //   Your Cheminova verification OTP is: ${otp}
    // );
    return res.status(200).json({
      message: `OTP sent to your mobile number ${fullMobileNumber} successfully`,
    });
  } catch (error) {
    res.status(500).json({
      message: error.message ? error.message : "Server error!",
    });
  }
};

export const verifyOtp = async (req, res) => {
  const { fullMobileNumber, otp } = req.body;

  try {
    let mobileNmr = fullMobileNumber?.trim();
    const territoryManager = await TerritoryManager.findOne({
      mobileNumber: mobileNmr,
    });

    if (!territoryManager) {
      return res.status(400).json({ message: "Invalid mobile number or OTP" });
    }

    if (
      territoryManager.otp !== otp ||
      territoryManager.otpExpires < Date.now()
    ) {
      return res.status(400).json({ message: "Invalid or expired OTP" });
    }
    const name = territoryManager.name;
    const mobile = territoryManager.mobileNumber;
    territoryManager.isVerified = true;
    territoryManager.otp = undefined;
    territoryManager.otpExpires = undefined;

    // Generate a random password
    const newPassword = password.randomPassword({
      length: 12,
      characters: [
        { characters: password.upper, exactly: 1 },
        { characters: password.symbols, exactly: 1 },
        password.lower,
        password.digits,
      ],
    });

    // Save the new password (hashed)
    territoryManager.password = newPassword;
    await territoryManager.save();

    // Send email with the new password
    await sendEmail({
      to: `${territoryManager?.email}`, // Change to your recipient
      from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
      subject: `Cheminova Account Created`,
      html: `Your Territory Manager Account is created successfully.
      <br/>name is: <strong>${name}</strong><br/>
      <br/>MobileNumber is: <strong>${mobile}</strong><br/>
      <br/>password is: <strong>${newPassword}</strong><br/><br/>If you have not requested this email, please ignore it.`,
    });

    const token = territoryManager.getJWTToken();
    res.status(200).json({
      success: true,
      token,
      message: "Mobile number verified and new password sent successfully",
    });
  } catch (error) {
    res.status(500).json({
      message: error.message ? error.message : "Server error!",
    });
  }
};
// Login TerritoryManager
export const loginTerritoryManager = async (req, res) => {
  const { email, password } = req.body;
  // console.log(email, password);
  try {
    if (!email || !password) {
      return res.status(400).json({ message: "Please Enter Email & Password" });
    }

    const territoryManager = await TerritoryManager.findOne({ email }).select(
      "+password"
    );

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

    const isPasswordMatched = await territoryManager.comparePassword(password);

    if (!isPasswordMatched) {
      return res.status(400).json({ message: "Invalid Email or Password" });
    }
    const token = territoryManager.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!",
    });
  }
};
// Logout User
export const logout = catchAsyncErrors(async (req, res, next) => {
  res.cookie("token", null, {
    expires: new Date(Date.now()),
    httpOnly: true,
  });

  res.status(200).json({
    success: true,
    message: "Logged Out",
  });
});
//get All territorymanager
export const getAllTerritoryManager = async (req, res) => {
  try {
    const PAGE_SIZE = parseInt(req.query?.show || "10");
    const page = parseInt(req.query?.page || "1") - 1;
    let filter = {};
    if (req.query?.name) {
      filter.name = {
        $regex: new RegExp(req.query.name, "i"),
      };
    }
    if (req.query?.mobileNumber) {
      filter.mobileNumber = {
        $regex: new RegExp(req.query.mobileNumber, "i"),
      };
    }
    if (req.query?.isVerified) {
      filter.isVerified = req.query.isVerified === "true";
    }

    const total = await TerritoryManager.countDocuments(filter);
    const territoryManager = await TerritoryManager.find(filter)
      .limit(PAGE_SIZE)
      .skip(PAGE_SIZE * page)
      .sort({ createdAt: -1 });

    return res.status(200).json({
      success: true,
      total_data: total,
      total_pages: Math.ceil(total / PAGE_SIZE),
      territoryManager,
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      message: error.message ? error.message : "Something went wrong!",
    });
  }
};

export const getOneTerritoryManager = async (req, res) => {
  try {
    if (!req.params.id) {
      return res
        .status(400)
        .json({ message: "Please provide sales coordinator ID" });
    }
    const territoryManager = await TerritoryManager.findById(req.params.id);
    if (territoryManager) {
      return res.status(200).json({
        success: true,
        message: "Fetched successfully",
        data: territoryManager,
      });
    } else {
      return res.status(404).json({
        success: false,
        message: "Sales coordinator not found",
      });
    }
  } catch (error) {
    return res.status(500).json({
      success: false,
      message: error.message ? error.message : "Something went wrong!",
    });
  }
};

// 4.Forgot Password

export const forgotPassword = async (req, res) => {
  const territorymanager = await TerritoryManager.findOne({
    email: req.body.email,
  });
  if (!req.body.email) {
    return res.status(400).json({ message: "please Enter Email!" });
  }
  if (!territorymanager) {
    return res.status(404).json({ message: "TerritoryManager not found" });
  }
  // Get ResetPassword Token
  // const resetToken = territorymanager.getResetPasswordToken(); //call function

  //save database reset token
  // await territorymanager.save({ validateBeforeSave: false });

  const passwords = password.randomPassword({
    length: 12,
    characters: [
      { characters: password.upper, exactly: 1 },
      { characters: password.symbols, exactly: 1 },
      password.lower,
      password.digits,
    ],
  });
  // console.log(passwords);
  territorymanager.password = passwords;
  await territorymanager.save();
  // const message = `Your password reset token are :- \n\n ${resetPasswordUrl} \n\nyour new password is:${password}\n\nIf you have not requested this email then, please ignore it.`;
  try {
    await sendEmail({
      to: `${territorymanager?.email}`, // Change to your recipient

      from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender

      subject: `Cheminova Password Recovery`,
      html: `your new password is: <br/> <strong> ${passwords}</strong><br/><br/>If you have not requested this email then, please ignore it.`,
    });

    res.status(200).json({
      success: true,
      message: `Email sent to ${territorymanager?.email} successfully`,
    });
  } catch (error) {
    territorymanager.resetPasswordToken = undefined;
    territorymanager.resetPasswordExpire = undefined;

    await territorymanager.save({ validateBeforeSave: false });

    return res.status(500).json({
      message: error.message ? error.message : "Something went wrong!",
    });
  }
};

//Update mobile Number
export const updateMobileNumber = async (req, res) => {
  const { id } = req.params;
  const userId = id || req.user._id;
  let { newCountryCode, newMobileNumber } = req.body;
  newCountryCode = newCountryCode?.trim();
  newMobileNumber = newMobileNumber?.trim();
  const newFullMobileNumber = `${newCountryCode}${newMobileNumber}`;

  try {
    const territorymanager = await TerritoryManager.findById(userId);
    if (!territorymanager) {
      return res.status(400).json({ message: "TerritoryManager not found" });
    }
    if (territorymanager.mobileNumber === newFullMobileNumber) {
      return res.status(400).json({
        message:
          "New mobile number cannot be the same as the old mobile number",
      });
    }
    // Check if the new mobile number already exists in another document
    const existingTerritoryManager = await TerritoryManager.findOne({
      mobileNumber: newFullMobileNumber,
    });

    if (existingTerritoryManager) {
      return res.status(400).json({
        message: "Mobile number already registered and verified by someone",
      });
    }
    // const otp = crypto.randomInt(100000, 1000000).toString();
    const otp = "123456";
    const otpExpires = Date.now() + 3 * 60 * 1000; // 3 minutes

    territorymanager.newMobileNumber = newFullMobileNumber;
    territorymanager.otp = otp;
    territorymanager.otpExpires = otpExpires;

    await territorymanager.save();
    await sendOtp(
      newFullMobileNumber,
      `Your Cheminova verification OTP is: ${otp}`
    );

    return res.status(200).json({
      message: `OTP sent to your new mobile number ${newFullMobileNumber} successfully`,
    });
  } catch (error) {
    console.error("Error updating mobile number:", error);
    return res.status(500).json({
      message: error.message ? error.message : "Server error!",
    });
  }
};

//verify Updated Number OTP
export const verifyUpdatedMobileOtp = async (req, res) => {
  const { newMobileNumber, otp } = req.body;
  // console.log(newMobileNumber, otp);
  try {
    let mobileNmr = newMobileNumber?.trim();
    const territoryManager = await TerritoryManager.findOne({
      newMobileNumber: mobileNmr,
    });

    if (!territoryManager) {
      return res.status(400).json({ message: "Invalid mobile number or OTP" });
    }

    if (
      territoryManager.otp !== otp ||
      territoryManager.otpExpires < Date.now()
    ) {
      return res.status(400).json({ message: "Invalid or expired OTP" });
    }

    // Update sales coordinator's mobile number and verification status
    territoryManager.mobileNumber = territoryManager.newMobileNumber;
    territoryManager.newMobileNumber = undefined;
    territoryManager.isVerified = true;
    territoryManager.otp = undefined;
    territoryManager.otpExpires = undefined;

    // Save changes to the database
    await territoryManager.save();

    const token = territoryManager.getJWTToken();
    return res.status(200).json({
      success: true,
      token,
      message: "Mobile number updated and verified successfully",
    });
  } catch (error) {
    console.error("Error verifying mobile OTP:", error);
    return res.status(500).json({
      message: error.message ? error.message : "Server error!",
    });
  }
};

//getmyProfile
export const getmyProfile = async (req, res) => {
  try {
    const myData = await TerritoryManager.findById(req.user?._id);
    if (myData) {
      return res.status(200).json({
        success: true,
        message: "feched!",
        myData,
      });
    }
  } catch (error) {
    return res.status(500).json({
      success: false,
      message: error.message ? error.message : "Something went wrong!",
    });
  }
};

//
export const deleteTerritoryManager = async (req, res) => {
  try {
    if (!req.params.id) {
      return res.status(400).json({
        success: false,
        message: "Please Provide TerritoryManager ID!",
      });
    }
    const getTerritoryManager = await TerritoryManager.findById(req.params.id);
    if (!getTerritoryManager) {
      return res.status(404).json({
        success: false,
        message: "territorymanager not Found!",
      });
    }

    //-------------------------//
    const territorymanager = await TerritoryManager.findByIdAndDelete(
      req.params.id
    );
    if (!territorymanager) {
      return res.status(404).json({ message: "territorymanager Not Found" });
    }
    await territorymanager.remove();
    res.status(200).json({
      success: true,
      message: "territorymanager Deleted Successfully!!",
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      message: error.message ? error.message : "Something went wrong!",
    });
  }
};

export const UpdateProfile = async (req, res) => {
  const { name, email } = req.body;
  const { id } = req.params;
  // console.log(name, email);
  const userId = id || req.user._id;
  // console.log(userId);
  // Validate email
  if (!validator.isEmail(email)) {
    return res.status(400).json({ message: "Invalid email address" });
  }

  try {
    const territoryManager = await TerritoryManager.findById(userId); // Use the ID from params

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

    if (!territoryManager.isVerified) {
      return res.status(400).json({ message: "TerritoryManager not verified" });
    }

    // Check if email is being changed and already exists
    if (email && email !== territoryManager.email) {
      const emailExists = await TerritoryManager.findOne({ email });
      if (emailExists && emailExists._id.toString() !== userId) {
        return res.status(400).json({
          message:
            "This Email ID is already in use by another TerritoryManager",
        });
      }
      territoryManager.email = email;
    }

    // Update name if provided
    if (name) {
      territoryManager.name = name;
    }

    // Save the updated territoryManager
    await territoryManager.save();

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

//change TerritoryManager password
export const ChangePassword = async (req, res) => {
  const { id } = req.params; // Retrieve id from req.params
  const { oldPassword, newPassword, confirmPassword } = req.body;
  const userId = id || req.user._id; // Use the ID from the URL or from the authenticated user

  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 territorymanager = await TerritoryManager.findById(userId).select(
      "+password"
    );

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

    const isPasswordMatched = await territorymanager.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" });
    }

    territorymanager.password = newPassword;
    await territorymanager.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 Otp = async (req, res) => {
  // const { name, mobileNumber } = req.body;
  try {
    // let territorymanager = await TerritoryManager.findOne({ mobileNumber });

    // if (territorymanager && territorymanager.isVerified) {
    //   return res.status(400).json({ message: 'TerritoryManager already registered and verified for This Mobile No.' });
    // }

    //      const otp = crypto.randomInt(100000, 1000000).toString();

    //     // const otp ="123456";

    // const otpExpires = Date.now() + 10 * 60 * 1000; // 10 minutes

    // if (territorymanager) {
    //   territorymanager.otp = otp;
    //   territorymanager.otpExpires = otpExpires;
    // } else {
    //   territorymanager = new TerritoryManager({ name, mobileNumber, otp, otpExpires });
    // }

    // await territorymanager.save();
    await sendOtp();

    // res.status(200).json({territorymanager, message: `OTP  ${otp} sent to your  mobile number successfully` });
  } catch (error) {
    res.status(500).json({
      message: error.message ? error.message : "Server error!",
    });
  }
};
