import {useCallback, useMemo} from 'react';
import {useInfiniteQuery} from 'react-query';
import {CHATS_QUERY_KEYS} from '@modules/chats/constants';
import {getUsersList} from '@modules/chats/services';
import {ChatUser} from '@modules/chats/interfaces';
import {useVisibleChatMembers} from '@modules/chats/store';
import {DEFAULT_LIMIT} from '@services/constants';
import {persistedUserId} from '@services/localStorage';

export type ChatSearchUser = ChatUser & {isInChannel?: boolean};

/**
 * This hook is used to search for users in the database
 * @param enabled - Whether the query is enabled
 * @param search - The search query
 * @param limit - The limit of users to fetch
 * @param isInChannel - Check each user if is in the channel (will show a description with this info)
 * @returns The users found
 */

export const useSearchUsers = ({
  enabled,
  search,
  limit = DEFAULT_LIMIT,
  isInChannel,
  filterMySelf = false,
}: {
  enabled?: boolean;
  search?: string;
  limit?: number;
  isInChannel?: boolean;
  filterMySelf?: boolean;
} = {}) => {
  const {data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage} =
    useInfiniteQuery(
      CHATS_QUERY_KEYS.searchUsers(search),
      params =>
        getUsersList({
          limit,
          cursor: params.pageParam,
          q: search || undefined,
        }),
      {
        getNextPageParam: lastPage => lastPage.nextCursor,
        enabled,
      },
    );
  const channelMembers = useVisibleChatMembers();

  const users: ChatSearchUser[] | undefined = useMemo(
    () =>
      data?.pages
        .flatMap(page => page.data)
        .filter(user => {
          if (filterMySelf) {
            return user.id !== persistedUserId?.toString();
          }
          return true;
        })
        .map(user => ({
          ...user,
          isInChannel: isInChannel ? channelMembers?.has(user.id) : false,
        })),
    [data?.pages, filterMySelf, isInChannel, channelMembers],
  );

  const getNextPage = useCallback(() => {
    const isFetching = isLoading || isFetchingNextPage;
    !isFetching && hasNextPage && fetchNextPage();
  }, [fetchNextPage, hasNextPage, isFetchingNextPage, isLoading]);

  return {
    users,
    isLoading,
    getNextPage,
    hasNextPage,
    isFetchingNextPage,
  };
};
