import React, { useCallback, useRef } from "react";

export interface SelectableListProps<T> {
  items: T[];
  selectedValue?: T | null;
  renderLabel: (item: T) => React.ReactNode;
  onSelect: (item: T) => void;
}

export const SelectableList = <T,>(
  props: SelectableListProps<T>,
): JSX.Element => {
  const { items, selectedValue, renderLabel, onSelect } = props;

  const listRef = useRef<HTMLUListElement | null>(null);

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLUListElement>) => {
      if (!items.length) return;

      const currentIndex = selectedValue ? items.indexOf(selectedValue) : -1;

      if (e.key === "ArrowDown") {
        e.preventDefault();
        const nextIndex =
          currentIndex < items.length - 1 ? currentIndex + 1 : 0;
        onSelect(items[nextIndex]);
      }

      if (e.key === "ArrowUp") {
        e.preventDefault();
        const prevIndex =
          currentIndex > 0 ? currentIndex - 1 : items.length - 1;
        onSelect(items[prevIndex]);
      }
    },
    [items, selectedValue, onSelect],
  );

  return (
    <ul
      ref={listRef}
      className="selectable-list"
      tabIndex={0}
      onKeyDown={handleKeyDown}
    >
      {items.map((item, index) => {
        const isSelected = selectedValue === item;
        const className = isSelected ? "selected" : "";

        return (
          <li key={index} onClick={() => onSelect(item)} className={className}>
            {renderLabel(item)}
          </li>
        );
      })}
    </ul>
  );
};
