const { Op } = require("sequelize");
const { User } = require("../../models");
const { getReqInformation, generateCode } = require("../../utils/Common");
const bcrypt = require("bcrypt");
const { success, error } = require("../../handlers");
const sendEmail = require("../../utils/SendEmail");
const axios = require("axios");
const envCredential = require("../../config");
const CLIENT_ID = envCredential.GOOGLE_CLIENT_ID;
const CLIENT_SECRET = envCredential.GOOGLE_SECRET_KEY;
const REDIRECT_URI = envCredential.GOOGLE_REDIRECT_URI;

const index = async (req, res) => {
  let user = req.session?.user ?? {};
  if (user?.userName) {
    return res.redirect("/");
  }
  let successMessage = req.flash("success")[0];
  let errorMessage = req.flash("error")[0];
  let { baseUrl, endPoint } = getReqInformation(req);
  return res.render("auth/login.ejs", {
    baseUrl,
    endPoint,
    errorMessage,
    successMessage,
    user,
  });
};

const register = async (req, res) => {
  let user = req.session?.user ?? {};
  if (user?.userName) {
    return res.redirect("/");
  }
  let successMessage = req.flash("success")[0];
  let errorMessage = req.flash("error")[0];
  let { baseUrl, endPoint } = getReqInformation(req);
  return res.render("auth/register.ejs", {
    baseUrl,
    endPoint,
    errorMessage,
    successMessage,
    user,
  });
};

const loginProcess = async (req, res) => {
  try {
    let payload = req.body;
    let user = await User.findOne({
      where: {
        [Op.or]: [
          {
            email: payload?.userName,
          },
          {
            userName: payload?.userName,
          },
        ],
        userType: {
          [Op.in]: ["user", "agent"],
        },
      },
    });

    if (!user) {
      req.flash("error", "Please enter valid email/username");
      return res.redirect("/login");
    }

    const isPasswordValid = await bcrypt.compare(
      payload?.password,
      user.password
    );
    if (!isPasswordValid) {
      req.flash("error", "Please enter valid password");
      return res.redirect("/login");
    }

    req.session.user = user;
    console.log(req.session);
    req.flash("success", "User logged in successfully!!");
    return res.redirect("/login");
  } catch (err) {
    req.flash("error", "Something went wrong!!");
    return res.redirect("/login");
  }
};

const logout = async (req, res) => {
  req.session.destroy();
  return res.redirect("/");
};

const checkUserName = async (req, res) => {
  try {
    let userName = req.body?.userName;
    let user = await User.findOne({
      where: {
        userName: userName?.trim(),
      },
    });

    if (user) {
      return success(res, {
        status: false,
        data: false,
      });
    }
    return success(res, {
      status: true,
      data: true,
    });
  } catch (err) {
    return success(res, {
      status: false,
      data: false,
    });
  }
};

const registerProcess = async (req, res) => {
  try {
    let payload = req.body;
    let user = await User.findOne({
      where: {
        email: payload?.email,
      },
    });
    if (user) {
      req.flash("error", "Entered email already exists!!");
      return res.redirect("/register");
    }
    let checkUserName = await User.findOne({
      where: {
        userName: payload?.userName,
      },
    });

    if (checkUserName) {
      req.flash("error", "Username already exists!!");
      return res.redirect("/register");
    }
    const hash = await bcrypt.hash(payload?.password, 10);
    payload["password"] = hash;
    user = await User.create(payload);
    req.flash("success", "User registered successfully!!");
    return res.redirect("/register");
  } catch (err) {
    req.flash("error", "Something went wrong!!");
    return redirect("/register");
  }
};

const forgetPassword = async (req, res) => {
  try {
    let user = {};
    if (user?.userName) {
      return res.redirect("/");
    }
    let successMessage = req.flash("success")[0];
    let errorMessage = req.flash("error")[0];
    let { baseUrl, endPoint } = getReqInformation(req);
    return res.render("auth/forget-password.ejs", {
      baseUrl,
      endPoint,
      errorMessage,
      successMessage,
      user,
    });
  } catch (err) {
    return res.redirect("/login");
  }
};

const forgetPasswordProcess = async (req, res) => {
  try {
    let payload = req.body;
    let user = await User.findOne({
      email: payload?.email,
    });
    const { baseUrl } = getReqInformation(req);
    console.log(user, "=-=-=user=-=-=-=");
    if (!user) {
      req.flash("error", "User with this email doesn't exists!!");
      return res.redirect("/forget-password");
    }
    let code = generateCode();
    user.verificationCode = code;
    await user.save();
    let data = {
      to: user.email,
      subject: "Forget Password",
      code: code,
      baseUrl,
    };
    console.log(data, "=-=-=-data-=-=-=");
    sendEmail("forget-password.handlebars", data);
    req.flash(
      "success",
      "Email send successfully. Please check your email and change your password"
    );
    return res.redirect("/forget-password");
  } catch (err) {
    req.flash("error", "Something went wrong!!");
    return res.redirect("/forget-password");
  }
};

const confirmPassword = async (req, res) => {
  try {
    let code = req?.params?.code;
    let successMessage = req.flash("success")[0];
    let errorMessage = req.flash("error")[0];
    let { baseUrl, endPoint } = getReqInformation(req);
    let user = await User.findOne({
      where: {
        verificationCode: code,
      },
    });
    if (!user) {
      req.flash("error", "Verification link expired!!");
      return res.redirect("/forget-password");
    }

    return res.render("auth/change-password.ejs", {
      baseUrl,
      endPoint,
      errorMessage,
      successMessage,
      code,
      user: {},
    });
  } catch (err) {
    console.log(err);
    req.flash("error", "Something went wrong!!");
    return res.redirect("/forget-password");
  }
};

const confirmPasswordProcess = async (req, res) => {
  try {
    let payload = req.body;
    if (payload?.password != payload?.confirmPassword) {
      req.flash("error", "Please enter both password same!!");
      return res.redirect("/confirm-password/" + payload?.code);
    }
    let user = await User.findOne({
      where: {
        verificationCode: payload?.code,
      },
    });
    if (!user) {
      req.flash("error", "Verification link expired!!");
      return res.redirect("/forget-password");
    }
    const hash = await bcrypt.hash(payload?.password, 10);
    user.password = hash;
    await user.save();
    req.flash("success", "Password changed successfully!!");
    return res.redirect("/forget-password");
  } catch (err) {
    req.flash("error", "Something went wrong!!");
    return res.redirect("/confirm-password/" + req.body?.code);
  }
};

const setLocationOfUserInSession = async (req, res) => {
  try {
    let payload = req.body;
    req.session.location = { lat: payload?.lat, long: payload?.long };
    console.log(req.session.location);
    return success(res, {
      msg: "Lat Long saved successfully!!",
    });
  } catch (err) {
    return error(res, {
      msg: "Something went wrong!!",
    });
  }
};

const googleLogin = async (req, res) => {
  try {
    const url = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=profile email`;
    return res.redirect(url);
  } catch (err) {
    return res.redirect("/login");
  }
};

const googleCallback = async (req, res) => {
  try {
    const { code } = req.query;

    const { data } = await axios.post("https://oauth2.googleapis.com/token", {
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET,
      code,
      redirect_uri: REDIRECT_URI,
      grant_type: "authorization_code",
    });
    console.log(data);
    const { access_token, id_token } = data;

    // Use access_token or id_token to fetch user profile
    const { data: profile } = await axios.get(
      "https://www.googleapis.com/oauth2/v1/userinfo",
      {
        headers: { Authorization: `Bearer ${access_token}` },
      }
    );
    let payload = profile;
    let names = payload?.name?.split(" ");
    let dataToSave = {
      userName: payload?.email,
      firstName: names.length > 0 ? names[0] : "",
      lastName: names.length > 1 ? names[1] : "",
      email: payload?.email,
      image: payload?.picture ?? "",
      isSocialSignup: true,
      socialType: "gmail",
    };

    let [user, created] = await User.findOrCreate({
      where: {
        email: dataToSave?.email,
      },
      defaults: dataToSave,
    });
    console.log(user, "=-=-=", created);
    if (!user?.isSocialSignup) {
      req.flash(
        "error",
        "Please login using email and password gmail login is not enabled for this account!!"
      );
      return res.redirect("/login");
    }
    req.session.user = user;
    return res.redirect("/");
  } catch (err) {
    console.log(err);
    return res.redirect("/login");
  }
};

module.exports = {
  index,
  register,
  loginProcess,
  logout,
  checkUserName,
  registerProcess,
  forgetPassword,
  forgetPasswordProcess,
  confirmPassword,
  confirmPasswordProcess,
  setLocationOfUserInSession,
  googleLogin,
  googleCallback,
};
