import { antdMessage as message } from "../../util/antdFeedback";
import dayjs from "../../util/day.js";
//import LogRocket from "logrocket";
import * as Sentry from "@sentry/electron/renderer";
import { sendPasswordResetEmail, signInWithEmailAndPassword, signOut } from "firebase/auth";
import { all, call, delay, put, takeLatest } from "redux-saga/effects";
import { auth, getCurrentUser, updateCurrentUser } from "../../firebase/firebase.utils";
import client from "../../graphql/GraphQLClient";
import { QUERY_BODYSHOP, QUERY_NOTIFICATIONS } from "../../graphql/bodyshop.queries";
import ipcTypes from "../../ipc.types";
import {
  checkForNotification,
  sendPasswordResetFailure,
  sendPasswordResetSuccess,
  setBodyshop,
  setNotification,
  setTargets,
  signInFailure,
  signInSuccess,
  signOutFailure,
  signOutSuccess,
  unauthorizedUser,
  updateUserDetailsSuccess
} from "./user.actions";
import UserActionTypes from "./user.types";

const { ipcRenderer } = window;

export function* onEmailSignInStart() {
  yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail);
}
export function* signInWithEmail({ payload: { email, password } }) {
  try {
    ipcRenderer.send(ipcTypes.app.toMain.track, {
      event: "SIGN_IN_ATTEMPT",
      email: email
    });
    const { user } = yield signInWithEmailAndPassword(auth, email, password);

    // const result = yield client.mutate({
    //   mutation: UPSERT_USER,
    //   variables: { authEmail: user.email, authToken: user.uid },
    // });
    if (user) {
      yield put(
        signInSuccess({
          uid: user.uid,
          email: user.email,
          displayName: user.displayName,
          photoURL: user.photoURL,
          authorized: true
        })
      );
    } else {
      yield put(signInFailure());
    }
  } catch (error) {
    yield put(signInFailure({ ...error, messagePretty: ErrorFormatter(error.code) }));
  }
}

export function* onCheckUserSession() {
  yield takeLatest(UserActionTypes.CHECK_USER_SESSION, isUserAuthenticated);
}

export function* isUserAuthenticated() {
  try {
    const user = yield getCurrentUser();
    if (!user) {
      yield put(unauthorizedUser());
      return;
    }

    yield put(
      signInSuccess({
        uid: user.uid,
        email: user.email,
        displayName: user.displayName,
        photoURL: user.photoURL,
        authorized: true
      })
    );
  } catch (error) {
    yield put(signInFailure(error));
  }
}

export function* onSignOutStart() {
  yield takeLatest(UserActionTypes.SIGN_OUT_START, signOutStart);
}

export function* signOutStart() {
  try {
    ipcRenderer.send(ipcTypes.app.toMain.track, {
      event: "SIGN_OUT"
    });
    ipcRenderer.send(ipcTypes.fileWatcher.toMain.stop);
    yield signOut(auth);
    yield put(signOutSuccess());
    localStorage.removeItem("token");
  } catch (error) {
    yield put(signOutFailure(error.message));
  }
}

export function* onUpdateUserDetails() {
  yield takeLatest(UserActionTypes.UPDATE_USER_DETAILS, updateUserDetails);
}
export function* updateUserDetails(userDetails) {
  try {
    yield updateCurrentUser(userDetails.payload);
    yield put(updateUserDetailsSuccess(userDetails.payload));
  } catch (error) {
    //yield put(signOutFailure(error.message));
    //TODO error handling
    console.log(error);
  }
}

export function* onSignInSuccess() {
  yield takeLatest(UserActionTypes.SIGN_IN_SUCCESS, signInSuccessSaga);
}

export function* signInSuccessSaga({ payload }) {
  //Query for the Correct Bodyshop
  ipcRenderer.send(ipcTypes.app.toMain.setUserName, payload.email);
  // LogRocket.identify(payload.email, {
  //   email: payload.email,
  // });
  //ipcRenderer.send(ipcTypes.app.toMain.checkForUpdates);

  ipcRenderer.send(ipcTypes.app.toMain.track, {
    event: "SIGN_IN_SUCCESS",
    email: payload.email
  });
  const shop = yield client.query({ query: QUERY_BODYSHOP });
  if (shop.data.bodyshops.length > 0) {
    yield put(setBodyshop(shop.data.bodyshops[0]));
    ipcRenderer.send(ipcTypes.app.toMain.setAcceptableInsCoNm, shop.data.bodyshops[0].accepted_ins_co);
    ipcRenderer.send(ipcTypes.app.toMain.setInsRuleSet, shop.data.bodyshops[0].ins_rule_set);

    ipcRenderer.send(ipcTypes.app.toMain.setReleaseChannel, shop.data.bodyshops[0].channel);
    ipcRenderer.send(ipcTypes.fileWatcher.toMain.start, {
      startup: true
    });
    yield put(checkForNotification());
    //Check for notifications, and continue to check.
    window.$crisp.push(["set", "user:company", [shop.data.bodyshops[0].shopname]]);
    window.$crisp.push(["set", "user:nickname", [payload.displayName || payload.email]]);
    window.$crisp.push(["set", "user:email", [payload.email]]);
    window.$crisp.push(["set", "session:segments", [["rps-user"]]]);
    ipcRenderer.send(ipcTypes.app.toMain.getAppVersion);

    Sentry.setUser({
      email: payload.email,
      username: payload.displayName || payload.email
    });
  } else {
    console.log("No bodyshop has been associated.");
    yield put(setBodyshop(false));
  }
  if (shop.data.targets.length > 0) {
    yield put(setTargets(shop.data.targets));
  } else {
    console.log("No bodyshop has been associated.");
    yield put(setTargets(null));
  }
  // LogRocket.identify(payload.email);
  // if (!payload.email.includes("@imex.")) yield put(setInstanceId(payload.uid));
  // yield logImEXEvent("redux_sign_in_success");
}

export function* onCheckForNotification() {
  yield takeLatest(UserActionTypes.CHECK_FOR_NOTIFICATION, checkForNotificationSaga);
}
export function* checkForNotificationSaga() {
  const {
    data: { notifications }
  } = yield client.query({
    query: QUERY_NOTIFICATIONS,
    variables: { now: dayjs() }
  });

  if (notifications) {
    yield put(setNotification(notifications));
  }
  yield delay(4 * 60 * 60 * 1000);
  yield put(checkForNotification());
}

export function* onSendPasswordResetStart() {
  yield takeLatest(UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START, sendPasswordResetEmailFunc);
}
export function* sendPasswordResetEmailFunc({ payload }) {
  try {
    ipcRenderer.send(ipcTypes.app.toMain.track, {
      event: "RESET_PASSWORD",
      email: payload
    });
    yield sendPasswordResetEmail(auth, payload);

    yield put(sendPasswordResetSuccess());
    message.success("Password reset sent succesfully.");
  } catch (error) {
    yield put(sendPasswordResetFailure(error.message));
  }
}
export function* userSagas() {
  yield all([
    call(onEmailSignInStart),
    call(onCheckUserSession),
    call(onSignOutStart),
    call(onUpdateUserDetails),
    call(onSignInSuccess),
    call(onSendPasswordResetStart),
    call(onCheckForNotification)
  ]);
}

const ErrorFormatter = (code) => {
  switch (code) {
    case "auth/invalid-email":
      return "Please enter a valid email.";
    case "auth/user-not-found":
      return "A user does not exist with that email.";
    case "auth/wrong-password":
      return "The email or password is incorrect.";
    default:
      return code;
  }
};
