import { ofType } from 'redux-observable';
import { concat, defer, EMPTY, of } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';

import { TYPE_ERROR, TYPE_INFO } from '@/modules/@common/notify/constants';
import { TOKEN_COOKIE_NAME, TOKEN_COOKIE_VALUE } from '@/modules/@common/token/constants';

import { impersonateUserAction } from '../slices';
import { notifyAction } from '@/modules/@common/notify/redux/slices';
import { getToken, setTokenCookieName, setTokenCookieValue } from '@/modules/@common/token/helpers';

export default (action$) =>
  action$.pipe(
    ofType(impersonateUserAction.type),
    switchMap(({ payload: userId }) => {
      const stream$ = defer(() => {
        const impersonateUser = async () => {
          const response = await fetch(`${process.env.APP_PCN_API_BASE_URL_FE}/private/users/impersonate`, {
            credentials: 'include',
            method: 'POST',
            headers: {
              Accept: 'application/json',
              Authorization: getToken(),
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              userId,
            }),
          });

          const result = await response.json();

          if (response.status !== 200) {
            throw new Error('Could not Login As');
          }

          try {
            await fetch(`${window.location.origin}/api/auth/login`, {
              method: 'POST',
              headers: {
                Accept: 'application/json',
                Authorization: getToken(),
                'Content-Type': 'application/json',
              },
              body: JSON.stringify({
                token: result.token,
                impersonateToken: getToken(),
                [TOKEN_COOKIE_NAME]: result?.cookieName,
                [TOKEN_COOKIE_VALUE]: result?.cookieValue,
              }),
            });
          } catch {
            // Should be changed later on, this is temporary
          }

          window.localStorage.clear();

          if (result?.cookieName) {
            setTokenCookieName(result.cookieName);
            setTokenCookieValue(result.cookieValue);
          }

          window.location.href = `${window.location.origin}/`;
        };

        return impersonateUser();
      }).pipe(
        switchMap(() => EMPTY),
        catchError(() =>
          of(
            notifyAction({
              type: TYPE_ERROR,
              message: 'Error Logging As',
            }),
          ),
        ),
      );

      return concat(
        of(
          notifyAction({
            type: TYPE_INFO,
            message: 'Start Logging As',
          }),
        ),
        stream$,
      );
    }),
  );
