import asyncHandler from "#middlewares/asyncHandler";
import { COINS } from "#constant/constant";
import { email, forgetEmail, conformEmail } from "#utils/email";
import { User, validate } from "#models/user_model";
import bcrypt from "bcrypt";

import otpGenerator from 'otp-generator';

import { UserVerification } from "#models/user_verification"




//@desc  Create User
//@route  /user
//@request Post Request
//@acess  public
const createSignUp = asyncHandler(async (req, res) => {
  const { error } = validate(req.body);
  if (error) {
    return res
      .status(400)
      .send({ status: false, message: error?.details[0]?.message });
  }

  const emailValid = await User.findOne({ email: req.body.email });

  if (emailValid) {
    return res
      .status(400)
      .json({ status: true, message: "email already exists" });
  }

  let user = new User(req.body);
  const salt = bcrypt.genSalt(10)

  user.password = await bcrypt.hash(user.password, parseInt(salt));
  user = await user.save();

  const checkedReset = await UserVerification.findOne({ email: req.body.email });

  if (checkedReset) {
    return res.status(200).json({ status: true, message: "Email Verification Sent Already" })
  }

  let uniqueString = otpGenerator.generate(6, {
    digits: true, upperCaseAlphabets: false, lowerCaseAlphabets: true, specialChars: false
  })

  let verification = new UserVerification({
    email: req.body.email,
    resetId: uniqueString,
  })
  verification = await verification.save();

  conformEmail(req.body.email, verification._id, uniqueString)

  return res
    .status(200)
    .json({ status: true, message: "User Registered Successfully!", user });
});



//@desc  User Get One
//@route  /user/:id
//@request Get Request
//@acess  private
const getOneUser = asyncHandler(async (req, res) => {

  const user = await User.findById(req.params.id);
  if (user) {
    return res.status(200).json({
      status: true,
      user
    })
  }
  else {
    return res.status(200).json({ status: true, message: "User record not found" });
  }
});


//@desc  Forget
//@route  /user/forget
//@request Get Request
//@acess  public
const forgetPassword = asyncHandler(async (req, res) => {

  let userFind = await User.findOne({ email: req.body?.email });
  console.log(userFind, "userFind")
  if (!userFind) {
    return res
      .status(400)
      .json({ status: true, message: "Email does not exists!" });
  }

  const checkedReset = await UserVerification.findOne({ email: req.body.email });

  if (checkedReset) {
    return res.status(200).json({ status: true, message: "Email Verification Sent Already" })
  }

  let uniqueString = otpGenerator.generate(6, {
    digits: true, upperCaseAlphabets: false, lowerCaseAlphabets: true, specialChars: false
  })

  let verification = new UserVerification({
    email: req.body.email,
    resetId: uniqueString,
  })
  verification = await verification.save();

  forgetEmail(req.body.email, verification._id, uniqueString)

  return res.status(200).json({ status: true, message: "Email Verification Sent" })

});


//@desc  Verify Email
//@route  /user/verified
//@request Post Request
//@acess  public
const verifyEmail = asyncHandler(async (req, res) => {
  let { id, resetId, email } = req.params;
  const checkedvalid = await UserVerification.findOne({ _id: id, resetId: resetId, email: email })
  if (checkedvalid) {
    // res.redirect(`http://wallet.pluton.ltd/update-password?email=${checkedvalid?.email}&resetId=${resetId}`)
    res.redirect(`http://localhost:3000/register?email=${checkedvalid.email}&resetId=${resetId}`)
  }
  else {
    return res.status(404).json({ status: true, message: "Failed To Verified" })
  }
})


//@desc  Verify Email
//@route  /user/verified
//@request Post Request
//@acess  public
const userVerifyByEmail = asyncHandler(async (req, res) => {
  let { id, resetId, email } = req.params;
  console.log(id, resetId, email);
  const checkedvalid = await UserVerification.findOne({ _id: id, resetId: resetId, email: email })
  console.log(checkedvalid, "checkedvalid");
  if (checkedvalid) {
    await User.findOneAndUpdate({ email: email }, { isVerified: true }, { new: true });
    await UserVerification.findOneAndDelete({ email: email });
    res.redirect(`http://localhost:3000/login`);
  }
  else {
    return res.status(404).json({ status: true, message: "Failed To Verified" })
  }
})

//@desc  update Password
//@route  /user/update
//@request Put Request
//@acess  public
const updatePassword = asyncHandler(async (req, res) => {

  const checkedvalid = await UserVerification.findOne({ email: req.body.email })
  if (!checkedvalid) {
    return res.status(400).json({ status: true, message: "Please verify email before password updated!" })
  }
  let salt, hashpassword, update;

  salt = bcrypt.genSalt(10)
  hashpassword = await bcrypt.hash(req.body.password, parseInt(salt));

  update = await User.findOneAndUpdate({ email: req.body.email }, { password: hashpassword }, { new: true });
  await UserVerification.findOneAndDelete({ email: req.body.email });
  return res.status(200).json({ status: true, message: "Password updated successfully", user: update })

})


// @desc    Update Email
// @route   PUT /user/update-email
// @access  Public
const updateEmail = asyncHandler(async (req, res) => {
  const { userId, oldEmail, newEmail } = req.body;

  // Find the user by userId and oldEmail
  const user = await User.findOne({ _id: userId, email: oldEmail });
  if (!user) {
    return res.status(400).json({ status: false, message: "Old email does not match our records or user not found." });
  }

  // Check if the new email already exists
  const emailExists = await User.findOne({ email: newEmail });
  if (emailExists) {
    return res.status(400).json({ status: false, message: "New email is already in use by another user." });
  }

  // Update the user's email
  user.email = newEmail;
  await user.save();

  // Optionally, delete any previous email verification records associated with the user
  await UserVerification.findOneAndDelete({ userId });

  return res.status(200).json({ status: true, message: "Email updated successfully", user });
});


// @desc    Update Role
// @route   PUT /user/update-role
// @access  Public
const updateIama = asyncHandler(async (req, res) => {
  const { userId, userRole } = req.body;

  // Find the user by userId and oldEmail
  const user = await User.findOne({ _id: userId, iama: userRole });
  if (!user) {
    return res.status(400).json({ status: false, message: "Old Role does not match our records or user not found." });
  }

  // Update the user's email
  user.iama = userRole;
  await user.save();

  return res.status(200).json({ status: true, message: "userRole updated successfully" });
});

//@desc  User All
//@route  /user
//@request Get Request
//@acess  private
const getAllUser = asyncHandler(async (req, res) => {
  const user = await User.find();
  if (user.length > 0) {
    return res.status(200).json({
      status: true,
      user
    })
  }
  else {
    return res.status(200).json({ status: true, message: "User record not exists" });
  }
});



/**
 @desc     Delete User
 @route    DELETE /api/user
 @access   Private
 */
const deleteUser = asyncHandler(async (req, res) => {

  const user = await User.findOneAndDelete(req.params.id);

  if (!user)
    return res?.status(200).send({ status: false, message: 'nothing to delete' })

  res?.status(200).send({ status: true, message: `User deleted successfully` })
})




export { getOneUser, createSignUp, forgetPassword, verifyEmail, userVerifyByEmail, updatePassword, getAllUser, deleteUser, updateEmail, updateIama}