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, useInput } from 'ra-core';
import { ReactElement, useCallback, useMemo } from 'react';
import { EntityField, EntityLookupDialog, RecordRepresentationType } from './common';

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

function ReferenceLookupInput(props: ReferenceLookupInputProps): 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__ne: value })
            .value()
        : propFilter,
    [propFilter, value]
  );
  const filters = useMemo(
    () => propFilters ?? [<SearchInput key="keyword" source="keyword" alwaysOn />],
    [propFilters]
  );

  const onAdd = useCallback(
    (ids: Identifier[]) => {
      const id = _.first(ids);
      handleClose();
      onChange(id);
      return id;
    },
    [onChange, handleClose]
  );

  const onDelete = useCallback(() => onChange(null), [onChange]);

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

export { ReferenceLookupInput };
export type { ReferenceLookupInputProps };
