import { useSortable } from '@wix/wix-style-react-incubator/dnd-kit/sortable';
import React, { HTMLAttributes, useEffect, useRef } from 'react';
import { CSS } from '@wix/wix-style-react-incubator/dnd-kit/utilities';
import { DraggableCardProps, GridCardItemProps } from '../DragAndDrop';
import { FiltersMap } from '@wix/bex-core';
import { observer } from 'mobx-react-lite';
import {
  dragHandleTestEvents,
  sortableItemTestEvents,
} from '../GridDragAndDropDndKit/dndTestEventHandlers';
import { addEventListener } from '@wix/bex-core/util';

function _DraggableListItem<T, F extends FiltersMap>(
  props: DraggableCardProps<T, F>,
) {
  const { children, id, isOverlay, dndDisabled, state } = props;
  const { type: CardItem, props: cardItemProps } = children;
  const { _dnd } = state;

  const isDropping = _dnd?.droppingId === id;

  const disabled = {
    draggable: dndDisabled,
    droppable: dndDisabled || state._dnd?.isActiveRectOutsideContainer,
  };

  const dragHandleRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (_dnd) {
      return addEventListener(_dnd.events, 'dropAnimationEnd', () => {
        _dnd.focusDragHandleIfDropped(id, dragHandleRef.current);
      });
    }

    return;
  }, [id, _dnd]);

  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
    setActivatorNodeRef,
  } = useSortable({
    id,
    transition: _dnd?.sortableAnimation,
    disabled,
  });

  const style = {
    position: 'relative' as const,
    width: '100%',
    transform: CSS.Transform.toString(transform),
    transition,
    visibility:
      (isDragging || isDropping) && !isOverlay
        ? ('hidden' as const)
        : undefined,
  };

  const testEvents =
    process.env.NODE_ENV === 'test' && state._dnd
      ? sortableItemTestEvents({ id, disabled, state: state._dnd })
      : undefined;

  const dndAttrs: Partial<HTMLAttributes<HTMLDivElement>> = {
    ...attributes,
    ...listeners,
    ...testEvents,
    onPointerDown: (e) => {
      state._dnd?.containerEvents.onPointerDown?.(e);
      listeners?.onPointerDown?.(e);
      testEvents?.onPointerDown?.(e);
    },
  };

  const ariaDescribedBy = `draggable-list-item-description-${id}`;

  const dragHandleProps: GridCardItemProps['dragHandleProps'] = isOverlay
    ? {}
    : {
        tabIndex: 0,
        domRef: (e) => {
          setActivatorNodeRef(e);
        },
        role: 'button',
        'aria-label': _dnd?.nullAnnouncements?.dragHandleLabel?.(id),
        'aria-describedby': ariaDescribedBy,
        onClick: (e) => e.stopPropagation(),
        ..._dnd?.handleEvents,
        ...(process.env.NODE_ENV === 'test' &&
          state._dnd &&
          dragHandleTestEvents({ id, state: state._dnd })),
      };

  return (
    <div ref={setNodeRef} {...dndAttrs} tabIndex={undefined} style={style}>
      <div id={ariaDescribedBy} style={{ display: 'none' }}>
        {state._dnd?.nullAnnouncements?.itemDescription?.(id)}
      </div>
      <CardItem
        {...cardItemProps}
        draggable
        droppable={_dnd?.isActive}
        dragging={isOverlay}
        dragHandleProps={dragHandleProps}
      />
    </div>
  );
}

export const DraggableListItem = observer(_DraggableListItem);
