import { useRef, type CSSProperties, type ReactNode } from 'react'
import { useVirtualizer } from '@tanstack/react-virtual'

/**
 * Windowed list: renders only the rows near the viewport, so a list thousands of
 * items long stays light — one DOM subtree per visible row, not per item. This
 * keeps the Downloads queue and a big channel's Library list responsive when a
 * source has 1000s of videos.
 *
 * It owns its own scroll container, so size that container via `style`/`className`
 * (e.g. `flex: 1` + `minHeight: 0`, or a `maxHeight`). Owning the scroller means
 * the virtualizer anchors at scroll offset 0 and never has to track where the
 * list sits within the page — robust even though the app shares one outer
 * scroll area with content above each list.
 *
 * Row heights are measured (measureElement), so variable-height rows are fine;
 * `estimateSize` only needs to be a rough first guess before measurement.
 */
export function VirtualList<T>({
  items,
  estimateSize,
  getKey,
  renderItem,
  overscan = 8,
  gap = 0,
  className,
  style
}: {
  items: T[]
  estimateSize: (index: number) => number
  getKey: (item: T, index: number) => string
  renderItem: (item: T, index: number) => ReactNode
  overscan?: number
  gap?: number
  className?: string
  style?: CSSProperties
}): React.JSX.Element {
  const scrollRef = useRef<HTMLDivElement>(null)
  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => scrollRef.current,
    estimateSize,
    overscan,
    gap,
    getItemKey: (index) => {
      const it = items[index]
      return it !== undefined ? getKey(it, index) : index
    }
  })

  return (
    <div ref={scrollRef} className={className} style={{ overflowY: 'auto', ...style }}>
      <div style={{ height: virtualizer.getTotalSize(), position: 'relative', width: '100%' }}>
        {virtualizer.getVirtualItems().map((vrow) => {
          const item = items[vrow.index]
          if (item === undefined) return null
          return (
            <div
              key={vrow.key}
              data-index={vrow.index}
              ref={virtualizer.measureElement}
              style={{
                position: 'absolute',
                top: 0,
                left: 0,
                width: '100%',
                transform: `translateY(${vrow.start}px)`
              }}
            >
              {renderItem(item, vrow.index)}
            </div>
          )
        })}
      </div>
    </div>
  )
}
