import { useState } from 'react';
import { useFormContext, Controller, ControllerProps } from 'react-hook-form';

import FilterList from '@material-hu/icons/material/FilterList';
import Checkbox from '@material-hu/mui/Checkbox';
import Chip from '@material-hu/mui/Chip';
import FormControl, { FormControlProps } from '@material-hu/mui/FormControl';
import FormHelperText from '@material-hu/mui/FormHelperText';
import InputLabel from '@material-hu/mui/InputLabel';
import ListSubheader from '@material-hu/mui/ListSubheader';
import MenuItem from '@material-hu/mui/MenuItem';
import Select, { SelectProps } from '@material-hu/mui/Select';
import Stack from '@material-hu/mui/Stack';

import useSegmentationGroups from 'src/hooks/queryHooks/useSegmentationGroups';
import { addOrRemove } from 'src/utils/arrayUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import CircularProgress from 'src/components/CircularProgress';

type Props = {
  rules?: ControllerProps['rules'];
  name: string;
  label?: string;
  selectProps?: SelectProps;
  formControlProps?: FormControlProps;
  excludedItemIds?: number[];
  filterIcon?: boolean;
  limitTags?: number;
};

// this component doesn't use FormSelect because we need nested items
function FormSelectSegmentationItem({
  name,
  rules,
  label,
  selectProps,
  formControlProps,
  excludedItemIds = [],
  filterIcon = false,
  limitTags = 3,
}: Props) {
  const { control } = useFormContext();
  const { t } = useLokaliseTranslation('general');

  const {
    data: segmentationGroups = [],
    isLoading: segmentationGroupsIsLoading,
  } = useSegmentationGroups({
    select: r => r.data,
  });

  // filter out excluded items and empty groups
  const filteredSegmentationGroups = segmentationGroups
    .map(group => ({
      ...group,
      items: group.items.filter(item => !excludedItemIds.includes(item.id)),
    }))
    .filter(({ items }) => items.length);

  const allItems = filteredSegmentationGroups.flatMap(sg => sg.items);

  // value needed to re-render Select when empty list, so it lost focus
  const [keyRender, setKeyRender] = useState(0);
  const handleDelete = (field, selected, limitedSelected) => {
    field.onChange(addOrRemove(selected, limitedSelected));
    if (selected.length === 1) {
      setKeyRender(keyRender + 1);
    }
  };

  const FilterIcon = filterIcon ? <FilterList sx={{ mr: 2 }} /> : undefined;

  return (
    <FormControl
      fullWidth
      {...formControlProps}
      key={keyRender}
    >
      <Controller
        control={control}
        name={name}
        rules={rules}
        render={({ field: { ref, ...field }, fieldState: { error } }) => (
          <>
            <InputLabel color={error ? 'error' : 'primary'}>{label}</InputLabel>
            <Select
              label={label}
              {...field}
              IconComponent={() =>
                segmentationGroupsIsLoading ? (
                  <CircularProgress
                    centered
                    size={15}
                    sx={{ mr: 2 }}
                  />
                ) : (
                  FilterIcon
                )
              }
              error={!!error}
              {...selectProps}
              inputRef={ref}
              renderValue={
                selectProps?.multiple
                  ? (selected: any[]) => {
                      const limitedSelected = selected.slice(0, limitTags);
                      const more = selected.length - limitedSelected.length;
                      return (
                        <Stack
                          direction="row"
                          sx={{
                            flexWrap: 'wrap',
                            gap: 0.5,
                            alignItems: 'center',
                          }}
                        >
                          {limitedSelected.map(ls => (
                            <Chip
                              key={ls}
                              label={allItems.find(o => o.id === ls)?.name}
                              onDelete={() => handleDelete(field, selected, ls)}
                              onMouseDown={event => {
                                event.stopPropagation();
                              }}
                            />
                          ))}
                          {more ? `+${more}` : null}
                        </Stack>
                      );
                    }
                  : undefined
              }
            >
              {!selectProps?.multiple && (
                <MenuItem value="">
                  <em>{t('none')}</em>
                </MenuItem>
              )}
              {filteredSegmentationGroups.flatMap(segmentationGroup => [
                <ListSubheader key={`group${segmentationGroup.id}`}>
                  {segmentationGroup.name}
                </ListSubheader>,
                ...segmentationGroup.items.map(item => (
                  <MenuItem
                    key={`item${item.id}`}
                    value={item.id}
                  >
                    {selectProps?.multiple && (
                      <Checkbox checked={field.value.includes(item.id)} />
                    )}
                    {item.name}
                  </MenuItem>
                )),
              ])}
            </Select>
            {error && <FormHelperText error>{error?.message}</FormHelperText>}
          </>
        )}
      />
    </FormControl>
  );
}

export default FormSelectSegmentationItem;
