import { IconButton } from '@/components/@extended';
import { LabeledInput, LabeledInputProps } from '@/components/ra-inputs/LabeledInput';
import { SearchInput } from '@/components/ra-inputs/SearchInput';
import { useDialogState } from '@/hooks';
import { AddCircleRounded } from '@mui/icons-material';
import { Stack } from '@mui/material';
import _ from 'lodash';
import { FilterPayload, Identifier, RaRecord, useInput } from 'ra-core';
import { ReactElement, useCallback, useMemo } from 'react';
import { EntityField, EntityLookupDialog, RecordRepresentationType } from './common';

type ReferenceManyLookupInputProps = {
  filter?: FilterPayload;
  filterDefaultValues?: object;
  filters?: ReactElement | ReactElement[];
  recordRepresentation?: RecordRepresentationType;
  reference: string;
} & LabeledInputProps;

function ReferenceManyLookupInput(props: ReferenceManyLookupInputProps): JSX.Element {
  const {
    children,
    filter: propFilter,
    filterDefaultValues,
    filters: propFilters,
    recordRepresentation,
    reference,
    source
  } = props;
  const { field } = useInput({ source });
  const { value, onChange } = field ?? {};
  const hasValue = !_.isEmpty(value);
  const { open, handleOpen, handleClose } = useDialogState(false);
  const filter = useMemo(
    () =>
      !_.isEmpty(value)
        ? _.chain(propFilter ?? {})
            .clone()
            .extend({ id__nin: value })
            .value()
        : propFilter,
    [propFilter, value]
  );
  const filters = useMemo(
    () => propFilters ?? [<SearchInput key="keyword" source="keyword" alwaysOn />],
    [propFilters]
  );

  const onAdd = useCallback(
    (ids: Identifier[]) => {
      const newValue = _.union(value ?? [], ids);
      handleClose();
      onChange(newValue);
      return newValue;
    },
    [onChange, handleClose, value]
  );

  const onDelete = useCallback((record: RaRecord) => onChange(_.without(value ?? [], record.id)), [onChange, value]);

  return (
    <LabeledInput {...props}>
      <Stack alignItems="center" direction="row" spacing={1}>
        {hasValue
          ? _.map(value ?? [], (id, index) => (
              <EntityField
                key={index}
                id={id}
                onDelete={onDelete}
                recordRepresentation={recordRepresentation}
                resource={reference}
              />
            ))
          : null}
        <IconButton onClick={handleOpen}>
          <AddCircleRounded />
        </IconButton>
        <EntityLookupDialog
          onCancel={handleClose}
          onConfirm={onAdd}
          multiple={true}
          slotProps={{
            dialog: { open, onClose: handleClose },
            list: {
              filter,
              filterDefaultValues,
              resource: reference
            },
            listToolbar: {
              filters: filters
            }
          }}
        >
          {children}
        </EntityLookupDialog>
      </Stack>
    </LabeledInput>
  );
}

export { ReferenceManyLookupInput };
export type { ReferenceManyLookupInputProps };
