const bcrypt = require("bcryptjs");
const _ = require("lodash");
const jwt = require("jsonwebtoken");
const config = require("config");
const { Users } = require("../../models/Users");
const moment = require("moment");
const { CompanyUsers } = require("../../models/CompanyUsers");

function gen_rand(length) {
  var result = "";
  var characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  var charactersLength = characters.length;
  for (var i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}

module.exports.signup = async (req, res) => {
  //name, email, password, role
  try {
    const { name, email, password, role, fcmToken } = req.body;
    const userFound = await Users.findOne({
      email: email,
      role: role,
    });
    if (userFound) {
      return res
        .status(401)
        .send({ error: "User with this email already exist" });
    }
    let newUser = new Users();
    const salt = await bcrypt.genSalt(10);
    newUser.name = name;
    newUser.email = email;
    newUser.role = role;
    newUser.fcmToken = fcmToken;
    newUser.password = await bcrypt.hash(password, salt);
    newUser = await newUser.save();

    const token = jwt.sign(
      {
        _id: newUser._id,
        role: newUser.role,
        name: newUser.name,
        email: newUser.email,
      },
      config.get("jwtPrivateKey")
    );
    newUser = JSON.parse(JSON.stringify(newUser));
    console.log("USER: ", newUser);
    newUser.token = token;

    return res.status(200).send(newUser);
  } catch (e) {
    console.log(e);
    return res.status(400).send({ error: e.message });
  }
};

module.exports.adminLogin = async (req, res) => {
  //email, password
  try {
    console.log("REQ BODY: ", req.body);
    const { email, password, role, fcmToken } = req.body;
    let user = await Users.findOne({
      email: email,
      role: role,
      isBlocked: false,
    });
    console.log("USER: ", user);
    if (!user)
      return res
        .status(400)
        .send({ error: "User with this email id doesn't exist." });
    const validPassword = await bcrypt.compare(password, user.password);
    console.log("validPassword: ", validPassword);
    if (!validPassword)
      return res.status(400).send({ error: "Password not matched" });
    const token = jwt.sign(
      {
        _id: user._id,
        role: user.role,
        name: user.name,
        email: user.email,
      },
      config.get("jwtPrivateKey")
    );

    user = JSON.parse(JSON.stringify(user));
    user.token = token;
    let dataToSent = {
      user: {
        name: user.name,
        email: user.email,
        _id: user._id,
        role: user.role,
      },
      accessToken: user.token,
    };

    await Users.findByIdAndUpdate(user._id, {
      $set: {
        fcmToken,
      },
    });
    // console.log("USER: ", user);
    return res.status(200).send(dataToSent);
  } catch (error) {
    return res.status(401).send({ error: "Error occured while login" });
  }
};

module.exports.adminAccessToken = async (req, res) => {
  try {
    console.log("Req body: ", req.body);
    let token = req.body.access_token;
    const decoded = jwt.verify(token, config.get("jwtPrivateKey"));
    let user = await Users.findOne({
      _id: decoded._id,
    });
    console.log("USER: ", user);
    if (!user) return res.status(400).send({ error: "Invalid token." });

    const newToken = jwt.sign(
      {
        _id: user._id,
        role: user.role,
        name: user.name,
        email: user.email,
      },
      config.get("jwtPrivateKey")
    );

    user = JSON.parse(JSON.stringify(user));
    user.token = newToken;
    let dataToSent = {
      user: {
        name: user.name,
        email: user.email,
        _id: user._id,
        role: user.role,
      },
      accessToken: user.token,
    };
    console.log("USER TO RETURN: ", dataToSent);
    return res.send(dataToSent);
  } catch (err) {
    console.log("Err unable to login", err);
    // winston.error(err);
    res.status(400).send({ error: "unable to Login" });
  }
};

module.exports.getAll = async (req, res) => {
  try {
    let user = await Users.find({}).sort({ updatedAt: -1 });
    user = JSON.parse(JSON.stringify(user));
    return res.status(200).send(user);
  } catch (e) {
    console.log(e);
    return res.status(400).send({ error: e.message });
  }
};

module.exports.forgotpassword = async (req, res) => {
  try {
    const { email, role } = req.body;
    let user = await Users.findOne({
      email: email,
      role: role,
    });
    if (!user)
      return res
        .status(400)
        .send({ error: "User with this email id doesn't exist." });
    var newPass = gen_rand(8);
    const salt = await bcrypt.genSalt(10);
    updatedPassword = await bcrypt.hash(newPass, salt);
    await Users.findByIdAndUpdate(
      { _id: user._id },
      { $set: { password: updatedPassword } }
    );

    var theHTML = `<b> Hi ${user.name}</b>, <br> You just request a password reset,
                   here is your new password: <br> <b>${newPass}</b>`;

    const msg = {
      to: email, // Change to your recipient
      from: "muqbausman@gmail.com", // Change to your verified sender
      subject: "Forgot Password",
      // text: "and easy to do anywhere, even with Node.js",
      html: theHTML,
    };
    sgMail
      .send(msg)
      .then(() => {
        console.log("Email sent");
        res
          .status(200)
          .send({ msg: "Email with new password sent successfully" });
      })
      .catch((error) => {
        console.error(error);
        res.status(400).send({ err: "Email don't work on this server yet " });
      });
  } catch (e) {
    console.log(e);
    return res.status(400).send({ error: e.message });
  }
};

module.exports.login = async (req, res) => {
  //email, password
  try {
    console.log("REQ BODY: ", req.body);
    const { email, password } = req.body;
    let user = await CompanyUsers.findOne({
      email: email,
    }).populate("company");
    console.log("USER: ", user);
    if (!user)
      return res
        .status(400)
        .send({ error: "User with this email id doesn't exist." });
    const validPassword = await bcrypt.compare(password, user.password);
    console.log("validPassword: ", validPassword);
    if (!validPassword)
      return res.status(400).send({ error: "Password/Email not matched" });
    if (user.isBlocked)
      return res.status(400).send({ error: "This user is blocked by admin" });
    const token = jwt.sign(
      {
        _id: user._id,
        role: user.role,
        name: user.name,
        email: user.email,
      },
      config.get("jwtPrivateKey")
    );

    user = JSON.parse(JSON.stringify(user));
    user.token = token;

    return res.status(200).send(user);
  } catch (error) {
    return res.status(401).send({ error: "Error occured while login" });
  }
};
