import React, { type FC, useMemo } from 'react';
import {
  type FetchNextPageOptions,
  type InfiniteQueryObserverResult,
} from 'react-query';

import { type AxiosResponse } from 'axios';
import Divider from '@material-hu/mui/Divider';
import Stack from '@material-hu/mui/Stack';
import { type SxProps } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';

import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuCheckbox from '@material-hu/components/design-system/Checkbox/Checkbox';
import StateCard from '@material-hu/components/design-system/StateCard';

import { type User } from 'src/types/user';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { type PaginatedResponse } from 'src/utils/tableUtils';

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

import AgentSelectionListItem from './AgentSelectionListItem';

type Props = {
  onSelectAll: () => void;
  onSelect: (agent: User) => void;
  selectedAgents: User[];
  agents: User[];
  loading: boolean;
  hasNextPage: boolean;
  isFetchingNextPage: boolean;
  fetchNextPage: (
    options?: FetchNextPageOptions,
  ) => Promise<
    InfiniteQueryObserverResult<
      AxiosResponse<PaginatedResponse<User>, unknown>,
      unknown
    >
  >;
  isSuccess: boolean;
  isEmpty: boolean;
  isEmptySearch: boolean;
  containerCardSx?: SxProps;
  disabledSelectAll?: boolean;
  checkDisabledFunction?: (agent: User) => boolean;
  isUserSelector?: boolean;
  allSelected?: boolean;
};

const AgentSelector: FC<Props> = ({
  onSelectAll,
  onSelect,
  selectedAgents,
  agents,
  loading,
  hasNextPage,
  isFetchingNextPage,
  fetchNextPage,
  isSuccess,
  isEmpty,
  isEmptySearch,
  containerCardSx = {},
  disabledSelectAll = false,
  isUserSelector = false,
  checkDisabledFunction = () => false,
  allSelected: allSelectedProp,
}) => {
  const { t } = useLokaliseTranslation('service_management');

  const allSelected = useMemo(() => {
    if (agents.length === 0) {
      return false;
    }

    return agents.every(agent =>
      selectedAgents.some(selected => selected.id === agent.id),
    );
  }, [selectedAgents, agents]);

  // Use the prop value if provided, otherwise use the computed value
  const allSelectedToShow =
    allSelectedProp !== undefined ? allSelectedProp : allSelected;

  const isSelected = (agent: User) => {
    return (
      selectedAgents.some(a => a.id === agent.id) ||
      (isUserSelector && !!agent.isAgent)
    );
  };

  return (
    <HuCardContainer
      fullWidth
      color="grey"
      sx={{
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        overflow: 'auto',
        ...containerCardSx,
      }}
    >
      {isEmpty && (
        <StateCard
          title={t('empty_agents_title')}
          description={t('empty_agents_helper_text')}
          slotProps={{
            card: {
              sx: {
                border: 'none',
                backgroundColor: ({ palette }) =>
                  palette.new.background.elements.grey,
              },
            },
          }}
        />
      )}
      {isEmptySearch && (
        <StateCard
          title={t('empty_agents_search_title')}
          description={t('empty_agents_search_helper_text')}
          slotProps={{
            card: {
              sx: {
                border: 'none',
                backgroundColor: ({ palette }) =>
                  palette.new.background.elements.grey,
              },
            },
          }}
        />
      )}
      {!isEmpty && !isEmptySearch && (
        <InfiniteList
          hasNextPage={hasNextPage}
          isSuccess={isSuccess}
          isFetchingNextPage={isFetchingNextPage}
          fetchNextPage={fetchNextPage}
          isLoading={loading}
          isEmpty={agents.length === 0}
        >
          <Stack sx={{ width: 1, height: '100%' }}>
            <Stack
              sx={{
                alignItems: 'center',
                flexDirection: 'row',
                width: 1,
                gap: 0.5,
              }}
            >
              <HuCheckbox
                checked={allSelectedToShow}
                onChange={onSelectAll}
                indeterminate={allSelectedToShow}
                disabled={disabledSelectAll}
              />
              <Typography variant="globalS">{t('select_all')}</Typography>
            </Stack>
            <Divider sx={{ mt: 2 }} />
            <Stack sx={{ gap: 0 }}>
              {agents.map(agent => (
                <React.Fragment key={agent.id}>
                  <AgentSelectionListItem
                    agent={agent}
                    onSelect={onSelect}
                    selected={isSelected(agent)}
                    disabledCheckbox={checkDisabledFunction?.(agent)}
                    disabledPill={isUserSelector && agent.isAgent}
                  />
                </React.Fragment>
              ))}
            </Stack>
          </Stack>
        </InfiniteList>
      )}
    </HuCardContainer>
  );
};

export default AgentSelector;
