import { useCallback, useLayoutEffect, useRef, useState } from "react";
import {
  shouldVirtualizeThreadRows,
  virtualThreadRange,
  VIRTUAL_THREAD_ROW_HEIGHT
} from "./virtual-thread-range.js";

export function VirtualThreadRows({ items, renderItem, itemKey, scrollRootRef }) {
  const containerRef = useRef(null);
  const animationFrameRef = useRef(null);
  const [range, setRange] = useState(() => virtualThreadRange({
    count: items.length,
    viewportHeight: typeof window === "undefined" ? 844 : window.innerHeight
  }));
  const virtualized = shouldVirtualizeThreadRows(items.length);

  const measure = useCallback(() => {
    if (!virtualized) return;
    const root = scrollRootRef.current;
    const container = containerRef.current;
    if (!root || !container) return;
    const scrollTop = Math.max(0, root.getBoundingClientRect().top - container.getBoundingClientRect().top);
    const next = virtualThreadRange({ count: items.length, scrollTop, viewportHeight: root.clientHeight });
    setRange((current) => current.start === next.start
      && current.end === next.end
      && current.totalHeight === next.totalHeight ? current : next);
  }, [items.length, scrollRootRef, virtualized]);

  const scheduleMeasure = useCallback(() => {
    if (animationFrameRef.current !== null) return;
    animationFrameRef.current = requestAnimationFrame(() => {
      animationFrameRef.current = null;
      measure();
    });
  }, [measure]);

  useLayoutEffect(() => {
    if (!virtualized) return undefined;
    const root = scrollRootRef.current;
    if (!root) return undefined;
    measure();
    root.addEventListener("scroll", scheduleMeasure, { passive: true });
    window.addEventListener("resize", scheduleMeasure);
    const resizeObserver = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(scheduleMeasure);
    resizeObserver?.observe(root);
    return () => {
      root.removeEventListener("scroll", scheduleMeasure);
      window.removeEventListener("resize", scheduleMeasure);
      resizeObserver?.disconnect();
      if (animationFrameRef.current !== null) cancelAnimationFrame(animationFrameRef.current);
      animationFrameRef.current = null;
    };
  }, [measure, scheduleMeasure, scrollRootRef, virtualized]);

  if (!virtualized) return items.map(renderItem);

  return <div ref={containerRef} className="virtual-thread-list" style={{ height: range.totalHeight }}>
    {items.slice(range.start, range.end).map((item, index) => <div
      className="virtual-thread-row"
      key={itemKey(item)}
      style={{ transform: `translateY(${range.offsetTop + index * VIRTUAL_THREAD_ROW_HEIGHT}px)` }}
    >
      {renderItem(item)}
    </div>)}
  </div>;
}
