import {
  LOAD_USER_REQUEST,
  LOAD_USER_SUCCESS,
  LOAD_USER_FAIL,
  FORGOT_PASSWORD_REQUEST,
  FORGOT_PASSWORD_SUCCESS,
  FORGOT_PASSWORD_FAIL,
  RESET_PASSWORD_REQUEST,
  RESET_PASSWORD_SUCCESS,
  RESET_PASSWORD_FAIL,
  UPDATE_USER_PROFILE_REQUEST,
  UPDATE_USER_PROFILE_SUCCESS,
  UPDATE_USER_PROFILE_FAIL,
  REGISTER_USER_REQUEST,
  REGISTER_USER_SUCCESS,
  REGISTER_USER_FAIL,
  CLEAR_ERRORS,
  GET_END_USER_REQUEST,
  GET_END_USER_SUCCESS,
  GET_END_USER_FAIL
} from "../constants/userConstants";
import axios from "axios";
import { getSession } from "next-auth/react";
import qs from "qs";

// register a new user.
export const registerUser = userData => async dispatch => {
  try {
    dispatch({
      type: REGISTER_USER_REQUEST
    });

    // 1. # # # # # # # # # # # # #
    // First save the main user record.
    const config = {
      headers: {
        "Content-Type": "multipart/form-data"
      }
    };

    const userFormData = new FormData();
    userFormData.append("username", `${userData.mobile}-${userData.email}`);
    userFormData.append("email", userData.email);
    userFormData.append("password", userData.password);
    userFormData.append("role", userData.role);
    userFormData.append("phone", userData.mobile);
    // userFormData.append("approved", "pending");
    console.log("userFormData", userFormData);
    const response = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/auth/local/register`, userFormData, config);

    console.log(`Register user done:`);
    console.log(response);

    if (response?.data?.status == "fail") {
      return response;
    }
    // Immediately after user creation based on the role of the user we need to create entry into the corresponding extension table.

    // Do for End user
    if (userData.role === "endUser") {
      console.log("userdata", userData);
      // userData["userId"] = response.data.user.id;
      await registerEndUser({ ...userData, userId: response.data.user.id });
    }
    if (userData.role === "vendor") {
      console.log("userdata", userData);
      // userData["userId"] = response.data.user.id;
      await registerVendor({ ...userData, userId: response.data.user.id });
    }

    // console.log(`About to dispatch REGISTER_USER_SUCCESS`);
    dispatch({
      type: REGISTER_USER_SUCCESS
    });
  } catch (error) {
    console.log("Error while registering a user: ");
    console.log(error);

    dispatch({
      type: REGISTER_USER_FAIL,
      payload: error.response.data
    });
  }
};

const registerVendor = async vendorData => {
  const authUser = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/auth/local`, {
    identifier: vendorData.email,
    password: vendorData.password
  });
  console.log("jwt", authUser);
  const config = {
    headers: {
      Authorization: `Bearer ${authUser.data.jwt}`,
      "Content-Type": "application/json"
    }
  };

  const data = {
    data: {
      mobileNo: vendorData.mobile,
      name: vendorData.fullname,
      email: vendorData.email,
      user: authUser.data.user.id
    }
  };

  const response = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/vendors`, data, config);
  return response;
};

const registerEndUser = async vendorData => {
  const authUser = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/auth/local`, {
    identifier: vendorData.email,
    password: vendorData.password
  });
  console.log("jwt", authUser);
  const config = {
    headers: {
      Authorization: `Bearer ${authUser.data.jwt}`,
      "Content-Type": "application/json"
    }
  };

  const data = {
    data: {
      mobileNo: vendorData.mobile,
      name: vendorData.fullname,
      email: vendorData.email,
      user: authUser.data.user.id
    }
  };

  const response = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/end-users`, data, config);
  return response;
};

// register a new user.
export const loadUser = () => async dispatch => {
  const session = await getSession();
  if (session) {
    console.log("session", session);
    try {
      dispatch({
        type: LOAD_USER_REQUEST
      });

      const config = {
        headers: {
          Authorization: `Bearer ${session.jwt}`
        }
      };

      // Load the user.
      const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/users/me?populate[0]=profileImage&populate[1]=role`, config);
      console.log("response session", response);
      dispatch({
        type: LOAD_USER_SUCCESS,
        payload: { ...response.data }
      });
    } catch (error) {
      console.log("Error while loading a user: ");
      console.log(error);

      dispatch({
        type: LOAD_USER_FAIL,
        payload: error.response.data
      });
    }
  }
};

// update profile.
export const updateUserProfile = userData => async dispatch => {
  const session = await getSession();
  if (!session) {
    throw new Error("You are not authenticated currently. Only authenticated users can update their own profile.");
  }

  try {
    dispatch({
      type: UPDATE_USER_PROFILE_REQUEST
    });

    const config = {
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${session.jwt}`
      }
    };

    const response = await axios.put(
      `${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/users-permissions/users/me`,
      {
        password: userData.password,
        fullName: userData.fullName,
        aboutMe: userData.aboutMe
      },
      config
    );

    const profileImageFormData = new FormData();
    profileImageFormData.append("field", "profileImage");
    profileImageFormData.append("ref", "plugin::users-permissions.user");
    profileImageFormData.append("refId", response.data.id);
    profileImageFormData.append("files", userData.avatarFiles[0]);
    const profileImageUploadResponse = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/upload`, profileImageFormData, {
      headers: {
        Authorization: `Bearer ${session.jwt}`
      }
    });
    // console.log("Profile image update response:");
    // console.log(profileImageUploadResponse);

    dispatch({
      type: UPDATE_USER_PROFILE_SUCCESS,
      payload: response.data
    });
  } catch (error) {
    console.log("Error while updating a user profile: ");
    console.log(error);

    dispatch({
      type: UPDATE_USER_PROFILE_FAIL,
      payload: error.response.data
    });
  }
};

// forgot password.
export const forgotPassword = email => async dispatch => {
  try {
    dispatch({
      type: FORGOT_PASSWORD_REQUEST
    });

    const config = {
      headers: {
        "Content-Type": "application/json"
      }
    };

    const response = await axios.post(
      `${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/auth/forgot-password`,
      {
        email
      },
      config
    );

    dispatch({
      type: FORGOT_PASSWORD_SUCCESS,
      payload: response.data.ok ? "Please check your inbox for instructions to reset your password." : "Error generating reset password link"
    });
  } catch (error) {
    console.log("Error while generating password reset link: ");
    console.log(error);

    dispatch({
      type: FORGOT_PASSWORD_FAIL,
      payload: error.response.data
    });
  }
};

// reset password.
export const resetPassword = (code, password, passwordConfirmation) => async dispatch => {
  try {
    dispatch({
      type: RESET_PASSWORD_REQUEST
    });

    const config = {
      headers: {
        "Content-Type": "application/json"
      }
    };

    const response = await axios.post(
      `${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/auth/reset-password`,
      {
        code,
        password,
        passwordConfirmation
      },
      config
    );

    const { user, jwt } = response.data;

    dispatch({
      type: RESET_PASSWORD_SUCCESS,
      payload: jwt ? "Password reset successfully." : "Error while resetting password."
    });
  } catch (error) {
    console.log("Error while resetting password: ");
    console.log(error);

    dispatch({
      type: RESET_PASSWORD_FAIL,
      payload: error.response.data
    });
  }
};

// Clear errors
export const clearErrors = () => async dispatch => {
  dispatch({
    type: CLEAR_ERRORS
  });
};

/** End user record to be created alongwith user creation. */
/** This is an internal utility method which creates a end user when a user is created. */
export const finishEndUserOtpVerification = async verificationData => {
  // First save the main cp record.
  const config = {
    headers: {
      "Content-Type": "application/json"
    }
  };

  return await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/end-users/finish-otp-verification`, verificationData, config);
};

export const updateUserApprovalStatus = async ({ status }) => {
  const session = await getSession();
  if (!session) {
    console.log("You are not authorized, please login");
  }
  const config = {
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${session.jwt}`
    }
  };

  const response = await axios.put(
    `${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/users/${session.id}`,
    {
      approved: status
    },
    config
  );

  return response;
};

export const updateApprovalStatusAdmin = async ({ status, userId, rejectionReason }) => {
  const session = await getSession();
  if (!session) {
    console.log("You are not authorized, please login");
  }
  const config = {
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${session.jwt}`
    }
  };
  if (!status == "rejected") {
    rejectionReason = "";
  }
  const response = await axios.put(
    `${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/users/${userId}`,
    {
      approved: status,
      rejectionReason
    },
    config
  );

  return response;
};

export const updateActivityStatusAdmin = async ({ status, activityId, rejectionReason }) => {
  const session = await getSession();
  if (!session) {
    console.log("You are not authorized, please login");
  }
  const config = {
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${session.jwt}`
    }
  };
  if (status == "approved") {
    rejectionReason = "";
  }
  const response = await axios.put(
    `${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/experiences/${activityId}`,
    {
      data: {
        approved: status,
        rejectionReason
      }
    },
    config
  );

  return response;
};

export const getCurrentEndUser = () => async dispatch => {
  try {
    // console.log("here action");
    const session = await getSession();
    if (!session) {
      return;
    }
    console.log("session action", session);
    dispatch({
      type: GET_END_USER_REQUEST
    });

    const config = {
      headers: {
        "Content-type": "application/json",
        Authorization: `Bearer ${session.jwt}`
      }
    };

    const query = {
      populate: ["user"],
      filters: {
        user: {
          id: {
            $eq: session.id
          }
        }
      }
    };

    const queryString = qs.stringify(query, {
      encodeValuesOnly: true
    });
    console.log("querystring", query);
    const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_API_URL}/api/end-users/?${queryString}`, config);
    console.log("response enduser", response);
    dispatch({
      type: GET_END_USER_SUCCESS,
      payload: response.data.data[0]
    });
  } catch (error) {
    console.log("Error while fetching end user: ");
    console.log(error);

    dispatch({
      type: GET_END_USER_FAIL,
      payload: error.response.data
    });
  }
};