import { useEffect, useMemo, useRef } from 'react';

import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

import { ItemContext, useSortableListContext } from '../../context';
import { type ItemContextValue, type ItemProps } from '../../types';

const Item = ({ id, children, disabled = false }: ItemProps) => {
  const context = useSortableListContext();
  const {
    dragByHandler,
    isDraggable,
    hasDragOverlay,
    registerItem,
    unregisterItem,
  } = context;
  const itemRef = useRef<HTMLLIElement | null>(null);

  const itemIsDraggable = isDraggable ? isDraggable(id) : !disabled;

  const {
    attributes,
    listeners,
    setNodeRef,
    setActivatorNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({
    id,
    disabled: !itemIsDraggable,
  });

  let cursorStyle = 'grab';
  if (!itemIsDraggable) {
    cursorStyle = 'default';
  } else if (dragByHandler) {
    cursorStyle = 'unset';
  }

  const style = {
    opacity: isDragging && hasDragOverlay ? 0.4 : 1,
    transform: CSS.Transform.toString(transform),
    transition,
    listStyle: 'none',
    cursor: cursorStyle,
    ...(isDragging && { zIndex: 10 }),
  };

  const handleProps = { ...listeners, ...attributes };

  const handleListeners = dragByHandler ? listeners : undefined;
  const handleAttributes = dragByHandler ? attributes : undefined;
  const handleActivatorRef = dragByHandler ? setActivatorNodeRef : undefined;

  const itemContextValue: ItemContextValue = useMemo(
    () => ({
      listeners: handleListeners,
      attributes: handleAttributes,
      setActivatorNodeRef: handleActivatorRef,
      isDraggable: itemIsDraggable,
      isDragging,
    }),
    [
      handleListeners,
      handleAttributes,
      handleActivatorRef,
      itemIsDraggable,
      isDragging,
    ],
  );

  useEffect(() => {
    // Create a static context value for the overlay (no actual drag functionality needed)
    const overlayContextValue: ItemContextValue = {
      listeners: undefined,
      attributes: undefined,
      setActivatorNodeRef: undefined,
      isDraggable: itemIsDraggable,
      isDragging: false,
    };

    const overlayContent = (
      <ItemContext.Provider value={overlayContextValue}>
        {children}
      </ItemContext.Provider>
    );

    registerItem(id, overlayContent, itemRef.current);
    return () => {
      unregisterItem(id);
    };
  }, [id, children, itemIsDraggable, registerItem, unregisterItem]);

  return (
    <ItemContext.Provider value={itemContextValue}>
      <li
        ref={node => {
          setNodeRef(node);
          itemRef.current = node;
        }}
        style={style}
        {...(dragByHandler || !itemIsDraggable ? {} : handleProps)}
      >
        {children}
      </li>
    </ItemContext.Provider>
  );
};

Item.displayName = 'SortableList.Item';

export default Item;
