// scrollbar.jsx — custom overlay scrollbar with fade in/out
//
// Usage:
//   <CustomScrollbar targetRef={mainRef} variant="main" />
//
// Hooks into a scrollable element via ref, mirrors its scroll position with a
// thumb element absolutely positioned over it. Fades in on scroll or hover,
// fades out 1.4s after the user stops interacting.

const { useEffect, useRef, useState, useCallback } = React;

function CustomScrollbar({ targetRef, variant = "main" }) {
  const [visible, setVisible] = useState(false);
  const [thumb, setThumb] = useState({ top: 0, height: 0, hasOverflow: false });
  const [dragging, setDragging] = useState(false);

  const trackRef = useRef(null);
  const hideTimer = useRef(null);
  const hoveringTrack = useRef(false);

  const showAndScheduleHide = useCallback(() => {
    setVisible(true);
    clearTimeout(hideTimer.current);
    hideTimer.current = setTimeout(() => {
      if (!hoveringTrack.current && !dragging) setVisible(false);
    }, 1200);
  }, [dragging]);

  const updateThumb = useCallback(() => {
    const el = targetRef.current;
    if (!el) return;
    const { scrollTop, scrollHeight, clientHeight } = el;
    const hasOverflow = scrollHeight > clientHeight + 2;
    if (!hasOverflow) {
      setThumb({ top: 0, height: 0, hasOverflow: false });
      return;
    }
    const ratio = clientHeight / scrollHeight;
    const trackH = trackRef.current ? trackRef.current.offsetHeight : clientHeight;
    const minThumb = 32;
    const height = Math.max(minThumb, Math.round(trackH * ratio));
    const maxTop = trackH - height;
    const scrollRatio = scrollTop / (scrollHeight - clientHeight);
    const top = Math.round(maxTop * scrollRatio);
    setThumb({ top, height, hasOverflow: true });
  }, [targetRef]);

  useEffect(() => {
    const el = targetRef.current;
    if (!el) return;

    const onScroll = () => {
      updateThumb();
      showAndScheduleHide();
    };
    const onHover = () => { showAndScheduleHide(); };

    el.addEventListener("scroll", onScroll, { passive: true });
    el.addEventListener("mouseenter", onHover);
    el.addEventListener("mousemove", onHover);

    const ro = new ResizeObserver(updateThumb);
    ro.observe(el);
    if (el.firstElementChild) ro.observe(el.firstElementChild);

    updateThumb();

    return () => {
      el.removeEventListener("scroll", onScroll);
      el.removeEventListener("mouseenter", onHover);
      el.removeEventListener("mousemove", onHover);
      ro.disconnect();
      clearTimeout(hideTimer.current);
    };
  }, [targetRef, updateThumb, showAndScheduleHide]);

  // Drag-to-scroll on the thumb
  const onThumbDown = (e) => {
    e.preventDefault();
    e.stopPropagation();
    const el = targetRef.current;
    if (!el || !trackRef.current) return;
    setDragging(true);
    const startY = e.clientY;
    const startScroll = el.scrollTop;
    const trackH = trackRef.current.offsetHeight;
    const { scrollHeight, clientHeight } = el;
    const scale = (scrollHeight - clientHeight) / (trackH - thumb.height);

    const move = (ev) => {
      const dy = ev.clientY - startY;
      el.scrollTop = startScroll + dy * scale;
    };
    const up = () => {
      setDragging(false);
      window.removeEventListener("pointermove", move);
      window.removeEventListener("pointerup", up);
    };
    window.addEventListener("pointermove", move);
    window.addEventListener("pointerup", up);
  };

  if (!thumb.hasOverflow) return null;

  return (
    <div
      ref={trackRef}
      className={`rk-scroll-track ${variant === "sidebar" ? "rk-sidebar-scroll" : ""} ${visible || dragging ? "visible" : ""}`}
      onMouseEnter={() => { hoveringTrack.current = true; showAndScheduleHide(); }}
      onMouseLeave={() => { hoveringTrack.current = false; showAndScheduleHide(); }}
    >
      <div
        className={`rk-scroll-thumb ${dragging ? "dragging" : ""}`}
        style={{ top: thumb.top, height: thumb.height }}
        onPointerDown={onThumbDown}
      />
    </div>
  );
}

window.CustomScrollbar = CustomScrollbar;
