import { useEffect, useMemo, useState } from 'react';
import { useInfiniteQuery } from 'react-query';

import ListItem from '@material-hu/mui/ListItem';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import HuAutocomplete from '@material-hu/components/design-system/Inputs/Autocomplete';

import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { goalsKeys } from '../../queries';
import { getGoalFormulas } from '../../services';
import { type GoalFormulaChain } from '../../types';

const PAGINATION_LIMIT = 25;
const OPTION_HEIGHT = 74;

export type FormulaOption = {
  value: number;
  label: string;
  formula?: GoalFormulaChain;
};

const renderFormulaOption = (
  t: (key: string) => string,
  renderProps: React.HTMLAttributes<HTMLLIElement>,
  option: FormulaOption | null,
) => {
  if (!option) return null;

  const hasFormula = (option?.formula?.formulaCount ?? 0) > 0;

  const filteredProps = Object.fromEntries(
    Object.entries(renderProps).filter(([, value]) => value !== undefined),
  );

  return (
    <ListItem
      key={option.value}
      {...filteredProps}
    >
      <Stack
        sx={{
          width: '100%',
          height: `${OPTION_HEIGHT}px`,
          flexDirection: 'row',
          alignItems: 'center',
          justifyContent: 'space-between',
        }}
      >
        <Stack sx={{ flexDirection: 'row', alignItems: 'center' }}>
          <Stack>
            <Typography
              variant="globalXXS"
              fontWeight="fontWeightRegular"
              color={theme => theme.palette.new?.text.neutral.lighter}
            >
              {t('general:name')}
            </Typography>
            <Typography
              variant="globalS"
              fontWeight="fontWeightRegular"
              color={theme => theme.palette.new?.text.neutral.default}
            >
              {option.label}
            </Typography>
          </Stack>
        </Stack>
        {hasFormula && (
          <Stack>
            <Typography
              variant="globalXS"
              fontWeight="fontWeightRegular"
              color={theme => theme.palette.new?.text.neutral.lighter}
            >
              {t('ranges.title')}
            </Typography>
            <Typography
              variant="globalS"
              fontWeight="bold"
              color={theme => theme.palette.new?.text.neutral.default}
              sx={{ textAlign: 'end' }}
            >
              {option.formula?.formulaCount}
            </Typography>
          </Stack>
        )}
      </Stack>
    </ListItem>
  );
};

type Props = {
  value: FormulaOption | null;
  onChange: (option: FormulaOption | null) => void;
  disabled?: boolean;
};

const FormulasAutocomplete = ({ value, onChange, disabled }: Props) => {
  const HuGoThemeProvider = useHuGoTheme();
  const { t } = useLokaliseTranslation('goals');
  const [search, setSearch] = useState('');

  const basePagination = { page: 0, limit: PAGINATION_LIMIT };

  const {
    data: infiniteFormulas,
    isLoading,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery(
    goalsKeys.formulas(basePagination, search),
    ({ pageParam = basePagination.page }) => {
      const trimmedSearch = search?.trim();
      return getGoalFormulas({
        page: pageParam,
        limit: basePagination.limit,
        ...(trimmedSearch ? { q: trimmedSearch } : {}),
      });
    },
    {
      getNextPageParam: lastPage => {
        const { page, totalPages } = lastPage.data;
        return page < totalPages ? page + 1 : undefined;
      },
      keepPreviousData: true,
      staleTime: 5 * 60 * 1000,
    },
  );

  const formulas: FormulaOption[] = useMemo(
    () =>
      infiniteFormulas?.pages?.flatMap(page =>
        page.data.items.map((formula: GoalFormulaChain) => ({
          value: formula.id,
          label: formula.title,
          formula,
        })),
      ) || [],
    [infiniteFormulas],
  );

  const totalFormulas = infiniteFormulas?.pages?.[0]?.data?.count || 0;
  const hasOnlyOneFormula = totalFormulas === 1 && !search.trim();

  useEffect(() => {
    if (!isLoading && hasOnlyOneFormula && formulas.length > 0 && !value) {
      const formula = formulas[0];
      onChange(formula);
    }
  }, [isLoading, hasOnlyOneFormula, formulas, value, onChange]);

  if (hasOnlyOneFormula) {
    return null;
  }

  if (!isLoading && totalFormulas === 0) {
    return null;
  }

  return (
    <HuGoThemeProvider>
      <Stack sx={{ gap: 1 }}>
        <Typography
          variant="globalS"
          fontWeight="fontWeightSemiBold"
          color="new.text.neutral.default"
        >
          {t('general:formulas')}
        </Typography>
        <HuAutocomplete
          value={value}
          onChange={onChange}
          options={formulas}
          onInputChange={(_event, nextValue) => setSearch(nextValue)}
          loading={isLoading || isFetchingNextPage}
          hasMoreOptions={hasNextPage ?? false}
          onLoadMore={fetchNextPage}
          placeholder={t('formulas.select')}
          disabled={disabled ?? false}
          renderOption={(renderProps, option) =>
            renderFormulaOption(t, renderProps, option)
          }
          isOptionEqualToValue={(option, val) => option?.value === val?.value}
          isServerFiltered
        />
      </Stack>
    </HuGoThemeProvider>
  );
};

export default FormulasAutocomplete;
