import { useEffect, useState } from 'react';

import PageError from '~/src/components/PageError';
import PageLoading from '~/src/components/PageLoading';
import useFetchSessionUser from '~/src/hooks/useFetchSessionUser';
import { useAppRouter } from '~/src/lib/router2';

export enum GuardTypes {
  LOADING = 'LOADING',
  ERROR = 'ERROR',
  FORBIDDEN = 'FORBIDDEN',
}

export interface UseAuthGuardProps {
  employeeOnly?: boolean;
  adminOnly?: boolean;
}

const useAuthGuard = ({
  employeeOnly = false,
  adminOnly = false,
}: UseAuthGuardProps = {}) => {
  const sessionUser = useFetchSessionUser();
  const [isMounted, setIsMounted] = useState(false);
  const router = useAppRouter();

  const { isLoggedIn, userError } = sessionUser;

  useEffect(() => {
    setIsMounted(true);
  }, []);

  useEffect(() => {
    if (!isMounted) return;

    if (!isLoggedIn) {
      router.push(
        `/login?redirectPath=${encodeURIComponent(location.pathname + location.search)}`
      );
    }
  }, [isMounted, isLoggedIn, router]);

  const user = sessionUser.user;

  if (userError) {
    return {
      type: GuardTypes.ERROR,
      content: <PageError error={userError} />,
      user,
    };
  }

  // block until component has mounted, this means the nothing below
  // this line will ever render on the server
  if (!isMounted || !user) {
    return {
      type: GuardTypes.LOADING,
      isLoading: true,
      content: <PageLoading timeout={1000} />,
      user,
    };
  }

  if (employeeOnly || adminOnly) {
    const hasEmployeeAccess = employeeOnly && (user.isEmployee || user.isAdmin);
    const hasAdminAccess = adminOnly && user.isAdmin;

    if (!hasEmployeeAccess && !hasAdminAccess) {
      return {
        type: GuardTypes.FORBIDDEN,
        content: (
          <PageError
            error={{ message: 'You do not have access to this page.' }}
          />
        ),
        user,
      };
    }
  }

  return {
    ...sessionUser,
    content: undefined,
    user,
  };
};

export default useAuthGuard;
