import {
  useEffect,
  useMemo,
  useRef,
  useState,
  type MouseEventHandler,
  type ReactNode,
} from 'react';
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';

const PAGE_SIZE = 2;

type DeptProjectListProps<T> = {
  items: T[];
  getKey: (item: T) => string;
  renderItem: (item: T) => ReactNode;
  sortableItemIds?: string[];
  dropRef?: (node: HTMLDivElement | null) => void;
  className?: string;
  onContextMenu?: MouseEventHandler<HTMLDivElement>;
  empty?: ReactNode;
};

function mergeRefs(
  ...refs: Array<((node: HTMLDivElement | null) => void) | undefined>
) {
  return (node: HTMLDivElement | null) => {
    refs.forEach((ref) => ref?.(node));
  };
}

function chunkItems<T>(items: T[], size: number): T[][] {
  const pages: T[][] = [];
  for (let i = 0; i < items.length; i += size) {
    pages.push(items.slice(i, i + size));
  }
  return pages;
}

export function DeptProjectList<T>({
  items,
  getKey,
  renderItem,
  sortableItemIds,
  dropRef,
  className = '',
  onContextMenu,
  empty,
}: DeptProjectListProps<T>) {
  const rootRef = useRef<HTMLDivElement | null>(null);
  const pages = useMemo(() => chunkItems(items, PAGE_SIZE), [items]);
  const pageCount = pages.length;
  const paged = pageCount > 1;
  const [pageIndex, setPageIndex] = useState(0);

  useEffect(() => {
    setPageIndex((prev) => Math.min(prev, Math.max(0, pageCount - 1)));
  }, [pageCount]);

  useEffect(() => {
    const root = rootRef.current;
    if (!root || !paged) return;

    const onWheel = (event: WheelEvent) => {
      if (Math.abs(event.deltaY) < 1) return;
      event.preventDefault();
      const direction = event.deltaY > 0 ? 1 : -1;
      setPageIndex((prev) => Math.min(pageCount - 1, Math.max(0, prev + direction)));
    };

    root.addEventListener('wheel', onWheel, { passive: false });
    return () => root.removeEventListener('wheel', onWheel);
  }, [paged, pageCount]);

  const setRefs = mergeRefs((node) => {
    rootRef.current = node;
  }, dropRef);

  const listBody = items.length === 0 ? (
    empty
  ) : paged ? (
    <div className="board-project-list-viewport">
      <div className="board-project-list-page">
        {pages[pageIndex].map((item) => (
          <div key={getKey(item)} className="board-project-list-slot">
            {renderItem(item)}
          </div>
        ))}
        {pages[pageIndex].length < PAGE_SIZE &&
          Array.from({ length: PAGE_SIZE - pages[pageIndex].length }, (_, slot) => (
            <div
              key={`empty-${pageIndex}-${slot}`}
              className="board-project-list-slot board-project-list-slot--empty"
              aria-hidden="true"
            />
          ))}
      </div>
    </div>
  ) : (
    <div className="board-project-list-viewport">
      <div className="board-project-list-track">
        <div className="board-project-list-page">
          {pages[0].map((item) => (
            <div key={getKey(item)} className="board-project-list-slot">
              {renderItem(item)}
            </div>
          ))}
          {pages[0].length < PAGE_SIZE &&
            Array.from({ length: PAGE_SIZE - pages[0].length }, (_, slot) => (
              <div
                key={`empty-0-${slot}`}
                className="board-project-list-slot board-project-list-slot--empty"
                aria-hidden="true"
              />
            ))}
        </div>
      </div>
    </div>
  );

  const sortableIds = sortableItemIds ?? items.map(getKey);
  const wrappedBody =
    sortableItemIds && items.length > 0 ? (
      <SortableContext items={sortableIds} strategy={verticalListSortingStrategy}>
        {listBody}
      </SortableContext>
    ) : (
      listBody
    );

  return (
    <div
      ref={setRefs}
      className={`board-project-list board-project-list--2slots${paged ? ' is-paged' : ''}${className ? ` ${className}` : ''}`}
      onContextMenu={onContextMenu}
    >
      {wrappedBody}
      {paged && (
        <div className="board-project-list-steps" aria-hidden="true">
          {Array.from({ length: pageCount }, (_, index) => (
            <span
              key={index}
              className={`board-project-list-step${index === pageIndex ? ' is-active' : ''}`}
            />
          ))}
        </div>
      )}
    </div>
  );
}
