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

import { useDebounce } from '@material-hu/hooks/useDebounce';
import { IconZoomExclamation } from '@material-hu/icons/tabler';
import { Stack } from '@material-hu/mui/index';

import StateCard from '@material-hu/components/composed-components/StateCard';
import Checkbox from '@material-hu/components/design-system/Checkbox/Checkbox';
import Search from '@material-hu/components/design-system/Inputs/Search';
import ListItem from '@material-hu/components/design-system/List/components/ListItem';
import Title from '@material-hu/components/design-system/Title';

import { ORGANIZER_LIMIT } from 'src/constants/events';
import useGeneralError from 'src/hooks/useGeneralError';
import { getInvitableOrganizers, getUsers } from 'src/services/events';
import { type Event, EventOrganizerStatus } from 'src/types/events';
import { type User } from 'src/types/user';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { getNextCursor } from 'src/utils/pagination';
import { getFullName } from 'src/utils/userUtils';

import InfiniteList from 'src/components/list/InfiniteList';

import { eventsKeys } from '../../queries';
import { userInitials } from '../../utils';

type AddOrganizerDrawerProps = {
  selectedUsers: User[];
  onToggleUser: (user: User) => void;
  event?: Event;
  selectedGroupId?: number;
};

const AddOrganizerDrawer: FC<AddOrganizerDrawerProps> = props => {
  const { selectedUsers, onToggleUser, event, selectedGroupId } = props;
  const { t } = useLokaliseTranslation('events');
  const [search, setSearch] = useState('');
  const debouncedSearch = useDebounce(search);
  const showGeneralError = useGeneralError();

  const ORGANIZER_STATUS_LABEL = {
    [EventOrganizerStatus.PENDING]: t('invitation_pending'),
    [EventOrganizerStatus.ACCEPTED]: t('is_organizer'),
    [EventOrganizerStatus.REJECTED]: '',
  };

  const onQueryError = (err: unknown) =>
    showGeneralError(err, t('error_search_title'));

  const { data: invitableOrganizersData, ...invitableOrganizersDataProps } =
    useInfiniteQuery(
      eventsKeys.invitableOrganizers(event?.id as number, debouncedSearch),
      ({ pageParam = '' }) =>
        getInvitableOrganizers({
          id: event?.id as number,
          limit: ORGANIZER_LIMIT.DRAWER_DISPLAY,
          q: debouncedSearch,
          cursor: pageParam,
        }),
      {
        getNextPageParam: getNextCursor,
        onError: onQueryError,
        enabled: !!event?.id,
      },
    );

  const { data: usersData, ...usersDataProps } = useInfiniteQuery(
    [...eventsKeys.users(selectedGroupId), debouncedSearch],
    ({ pageParam = '' }) =>
      getUsers({
        groupId: selectedGroupId,
        limit: ORGANIZER_LIMIT.DRAWER_DISPLAY,
        q: debouncedSearch,
        cursor: pageParam,
      }),
    { getNextPageParam: getNextCursor, onError: onQueryError, enabled: !event },
  );

  const activeQuery = event ? invitableOrganizersDataProps : usersDataProps;

  const invitableOrganizers = event
    ? invitableOrganizersData?.pages.flatMap(page => page.data.items)
    : usersData?.pages.flatMap(page =>
        page.data.items.map(user => ({ user, organizer: null })),
      );

  return (
    <Stack
      sx={{
        gap: 2,
        p: 2,
        backgroundColor: theme => theme.palette.new.background.layout.default,
        borderRadius: 2,
      }}
    >
      <Title
        title={t('select_organizers_description')}
        variant="S"
      />
      <Search
        value={search}
        onChange={setSearch}
        placeholder={t('general:search')}
      />
      <Stack
        sx={{
          gap: 1,
          px: 2,
          backgroundColor: theme =>
            theme.palette.new.background.layout.tertiary,
          borderRadius: 2,
          border: theme =>
            `1px solid ${theme.palette.new.border.neutral.default}`,
          maxHeight: '380px',
          overflowY: 'auto',
        }}
      >
        <InfiniteList
          isSuccess={activeQuery?.isSuccess}
          hasNextPage={activeQuery?.hasNextPage}
          fetchNextPage={activeQuery?.fetchNextPage}
          isFetchingNextPage={activeQuery?.isFetchingNextPage}
          isLoading={activeQuery?.isLoading}
          isEmpty={activeQuery?.isSuccess && !invitableOrganizers?.length}
          showNoResultsMessage={false}
        >
          {invitableOrganizers?.map(({ user, organizer }) => (
            <Stack
              key={user.id}
              sx={{ flexDirection: 'row', alignItems: 'center' }}
            >
              <Checkbox
                label=""
                checked={
                  selectedUsers.some(u => u.id === user.id) ||
                  organizer?.status === EventOrganizerStatus.ACCEPTED ||
                  organizer?.status === EventOrganizerStatus.PENDING
                }
                onChange={() => onToggleUser(user)}
                disabled={
                  organizer?.status === EventOrganizerStatus.ACCEPTED ||
                  organizer?.status === EventOrganizerStatus.PENDING
                }
              />
              <ListItem
                avatar={{
                  src: user.profilePicture || undefined,
                  text: !user.profilePicture ? userInitials(user) : undefined,
                  color: 'primary',
                }}
                text={{
                  title: getFullName(user),
                  description: organizer
                    ? ORGANIZER_STATUS_LABEL[organizer?.status]
                    : '',
                }}
              />
            </Stack>
          ))}
        </InfiniteList>
        {invitableOrganizers?.length === 0 && !activeQuery?.isLoading && (
          <StateCard
            slotProps={{
              avatar: { Icon: IconZoomExclamation },
              title: {
                title: t('no_users_found_title'),
                description: t('no_users_found_description'),
              },
            }}
            cardContained={false}
          />
        )}
      </Stack>
    </Stack>
  );
};

export default AddOrganizerDrawer;
