import { Button } from '@material-ui/core';
import api from 'api/api';
import Loading from 'components/Loading';
import { useSnackbar } from 'notistack';
import React, { FC, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { Redirect, useLocation } from 'react-router-dom';

import {
  selectIsSignedIn,
  selectLoading,
  selectUserRoles,
  User,
} from './userSlice';

type ProtectedProps = {
  redirect?: string;
  awaitAuth?: boolean;
  roles?: User['preferences']['roles'];
};
const Protected: FC<ProtectedProps> = ({
  children,
  redirect,
  awaitAuth,
  roles,
}) => {
  const isSignedIn = useSelector(selectIsSignedIn);
  const loading = useSelector(selectLoading);
  const userRoles = useSelector(selectUserRoles);
  const location = useLocation();
  const { enqueueSnackbar, closeSnackbar } = useSnackbar();
  const userRoleCheck = !(
    roles &&
    roles.length > 0 &&
    !roles.some(role => userRoles?.includes(role))
  );
  useEffect(() => {
    if (awaitAuth && !loading && (!isSignedIn || !userRoleCheck)) {
      const message = !isSignedIn
        ? 'You must be logged in to access this page'
        : 'Your account is not authorised to access this page';
      enqueueSnackbar(message, {
        variant: 'warning',
        key: 'protected-route-user-not-allowed',
        action: !isSignedIn
          ? () => (
              <Button
                onClick={() => {
                  api.signIn();
                  closeSnackbar();
                }}
              >
                Log In
              </Button>
            )
          : null,
      });
    }
  }, [
    awaitAuth,
    loading,
    closeSnackbar,
    enqueueSnackbar,
    isSignedIn,
    userRoleCheck,
  ]);
  if (awaitAuth && loading) return <Loading />;
  if (!isSignedIn || !userRoleCheck)
    return redirect ? (
      <Redirect
        to={{
          pathname: redirect,
          state: { referrer: !isSignedIn ? location.pathname : '/' },
        }}
      />
    ) : null;
  return <>{children}</>;
};

export default Protected;
