import { type FC, useState } from 'react';
import { useFormContext } from 'react-hook-form';
import { useInfiniteQuery } from 'react-query';

import { useDebounce } from '@material-hu/hooks/useDebounce';
import HuTitle from '@material-hu/components/design-system/Title';

import useRequiredParams from 'src/hooks/useRequiredParams';
import { getAssignableMembers } from 'src/services/groups';
import { type User } from 'src/types/user';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { getFullName } from 'src/utils/userUtils';

import FormAutocomplete from 'src/components/FormInputs/FormAutocomplete';
import { FormUserAutocompleteItem } from 'src/components/FormInputs/FormUserAutocomplete';
import { InfiniteList } from 'src/components/list';

import { groupsKeys } from '../../queries';

const LIMIT = 30;

type Props = {
  enabled: boolean;
};

export const FormAutocompleteGroupMemberSelect: FC<Props> = props => {
  const { enabled } = props;

  const { t } = useTranslation(['group']);
  const [search, setSearch] = useState('');
  const debouncedSearch = useDebounce(search);
  const { id: groupId } = useRequiredParams(['id']);
  const { watch } = useFormContext();
  const {
    data: infiniteAssignableMembers,
    isLoading: isLoadingAssignableMembers,
    isFetching: isFetchingNextPage,
    fetchNextPage,
    hasNextPage,
  } = useInfiniteQuery(
    groupsKeys.assignableMembers(groupId, {
      search: debouncedSearch,
    }),
    ({ pageParam = 1 }) =>
      getAssignableMembers(groupId, {
        limit: LIMIT,
        page: pageParam,
        search: debouncedSearch,
      }),
    {
      getNextPageParam: lastPage =>
        lastPage.data.page < lastPage.data.totalPages
          ? lastPage.data.page + 1
          : undefined,
      enabled,
    },
  );
  const assignableMembers =
    infiniteAssignableMembers?.pages.flatMap(page => page.data.items) || [];
  const selectedMembers = watch('selectedMembers');

  const filter = (
    options: User[], // hide already selected user
  ) =>
    options.filter(
      u => ![...selectedMembers?.map((s: User) => s.id)].includes(u.id),
    );

  return (
    <FormAutocomplete
      name="selectedMembers"
      filterOptions={options => filter(options)}
      getOptionLabel={option => getFullName(option)}
      options={assignableMembers}
      loading={isLoadingAssignableMembers}
      renderOption={FormUserAutocompleteItem(false, false)}
      hideCheckbox
      isOptionEqualToValue={(option, value) => option.id === value.id}
      query={setSearch}
      limitTags={0}
      noOptionsText={
        search !== debouncedSearch || isLoadingAssignableMembers ? null : (
          <HuTitle
            variant="S"
            title={t('general:empty_search_result')}
            description={t('general:empty_search_description')}
          />
        )
      }
      infinite={
        <InfiniteList
          isSuccess={!!infiniteAssignableMembers}
          isLoading={isLoadingAssignableMembers}
          isEmpty={
            !isLoadingAssignableMembers && assignableMembers.length === 0
          }
          fetchNextPage={fetchNextPage}
          hasNextPage={hasNextPage}
          isFetchingNextPage={isFetchingNextPage}
        >
          <div />
        </InfiniteList>
      }
      textFieldProps={{
        variant: 'outlined',
        margin: 'dense',
        placeholder: t('group:search_users'),
        sx: {
          backgroundColor: theme =>
            theme.palette.new.background.layout.tertiary,
          borderRadius: 1,
          '& .MuiAutocomplete-tag': { display: 'none' },
        },
      }}
      multiple
      hideEndAdornment
    />
  );
};
