import { useState } from 'react';
import { useInfiniteQuery } from 'react-query';

import { useDebounce } from '@material-hu/hooks/useDebounce';
import { useHuPagination } from '@material-hu/hooks/useHuPagination';

import useGeneralError from 'src/hooks/useGeneralError';
import { getRoleList } from 'src/services/rolesAndPermissions';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { flatPages } from 'src/utils/tableUtils';

import { rolesAndPermissionsKeys } from '../queries';
import { RoleState, RoleType } from '../types';

import useRolesPermissions from './useRolesPermissions';

const LIMIT = 10;

const useInfiniteRolesSearch = () => {
  const { canManageOrDefineRoles } = useRolesPermissions();
  const defaultState = canManageOrDefineRoles ? null : RoleState.ACTIVE;
  const [state, setState] = useState<RoleState | null>(defaultState);
  const showGeneralError = useGeneralError();
  const { t } = useLokaliseTranslation('rolesAndPermissions');

  const { Search, params, form } = useHuPagination({
    defaultOrderBy: 'updatedAt',
    defaultOrder: 'DESC',
  });

  const search = params.search;
  const debouncedQuery = useDebounce(search);

  const { data, isLoading, fetchNextPage, isFetchingNextPage, refetch } =
    useInfiniteQuery(
      rolesAndPermissionsKeys.all(debouncedQuery, state),
      ({ pageParam = 0 }) =>
        getRoleList({
          q: debouncedQuery,
          page: pageParam,
          limit: LIMIT,
          state,
          sort: params.order,
          sortBy: params.orderBy,
        }),
      {
        getNextPageParam: lastPage =>
          lastPage.data.page === lastPage.data.totalPages
            ? undefined
            : lastPage.data.page + 1,
        onError: err => showGeneralError(err, t('table.error_loading_roles')),
      },
    );

  const allResults = flatPages(data!) || [];

  const { nonCustom, custom } = allResults.reduce(
    (acc, role) => {
      if (role.type !== RoleType.CUSTOM) {
        acc.nonCustom.push(role);
      } else {
        acc.custom.push(role);
      }
      return acc;
    },
    {
      nonCustom: [] as typeof allResults,
      custom: [] as typeof allResults,
    },
  );

  const results = [...nonCustom, ...custom];

  return {
    search: {
      component: Search,
      value: search,
      state,
    },
    table: {
      results,
      totalCount: data?.pages[0]?.data?.count || 0,
    },
    loading: {
      isLoading,
      isFetchingNextPage,
    },
    actions: {
      fetchNextPage,
      setState,
      refetch,
    },
    form,
  };
};

export default useInfiniteRolesSearch;
