import { useState, type ReactNode } from 'react'
import { Input } from '../../primitives/Input/Input'
import { Button } from '../../primitives/Button/Button'
import styles from './EntityList.module.css'

interface EntityListProps<T> {
  items: T[]
  renderItem: (item: T, isSelected: boolean) => ReactNode
  getItemId: (item: T) => string
  selectedId?: string
  onSelect?: (id: string) => void
  searchPlaceholder?: string
  onSearch?: (query: string) => void
  addLabel?: string
  onAdd?: () => void
  emptyMessage?: string
  className?: string
}

export function EntityList<T>({
  items,
  renderItem,
  getItemId,
  selectedId,
  onSelect,
  searchPlaceholder = 'Search...',
  onSearch,
  addLabel,
  onAdd,
  emptyMessage = 'No items found',
  className,
}: EntityListProps<T>) {
  const [searchValue, setSearchValue] = useState('')
  const showHeader = !!onSearch || !!onAdd

  function handleSearchChange(e: React.ChangeEvent<HTMLInputElement>) {
    const value = e.target.value
    setSearchValue(value)
    onSearch?.(value)
  }

  function handleSearchClear() {
    setSearchValue('')
    onSearch?.('')
  }

  return (
    <div className={`${styles.entityListRoot} ${className ?? ''}`}>
      {showHeader && (
        <div className={styles.listHeader}>
          {onSearch && (
            <Input
              placeholder={searchPlaceholder}
              value={searchValue}
              onChange={handleSearchChange}
              onClear={handleSearchClear}
              className={styles.listHeaderSearch}
            />
          )}
          {onAdd && addLabel && (
            <Button size="sm" variant="secondary" onClick={onAdd}>
              {addLabel}
            </Button>
          )}
        </div>
      )}

      <div className={styles.list} role="listbox">
        {items.map((item) => {
          const id = getItemId(item)
          const isSelected = id === selectedId
          return (
            <div
              key={id}
              className={`${styles.entityItem} ${isSelected ? styles.entityItemSelected : ''}`}
              onClick={() => onSelect?.(id)}
              role="option"
              tabIndex={0}
              aria-selected={isSelected}
              onKeyDown={(e) => {
                if (e.key === 'Enter' || e.key === ' ') {
                  e.preventDefault()
                  onSelect?.(id)
                }
              }}
            >
              {renderItem(item, isSelected)}
            </div>
          )
        })}
        {items.length === 0 && (
          <div className={styles.emptyMessage}>{emptyMessage}</div>
        )}
      </div>
    </div>
  )
}
