import { useEffect, useRef, RefObject } from 'react';

/**
 * Among all elements matching the active-thumbnail data attribute, return the
 * one that is actually visible on screen.  Infinite-scroll carousels duplicate
 * slides as clones, so multiple DOM nodes can carry the marker at the same
 * time — but only one of them sits inside the carousel's visible area.
 */
const findVisibleActive = (): HTMLElement | null => {
  const candidates = document.querySelectorAll<HTMLElement>(
    '[data-adl-thumbnail-active]',
  );

  if (candidates.length <= 1) return candidates[0] ?? null;

  const vw = window.innerWidth;

  for (const el of candidates) {
    const r = el.getBoundingClientRect();
    // The element's horizontal center must be within the viewport.
    const cx = r.left + r.width / 2;
    if (cx >= 0 && cx <= vw) return el;
  }

  return null;
};

/**
 * Directly syncs the position, size, border-radius, and background-image of
 * the visible active thumbnail from the widget DOM onto a portal clone element
 * via direct style mutation.
 *
 * Direct DOM mutation means the clone updates in the same animation frame as
 * the position read, giving pixel-perfect sync even during CSS transitions.
 *
 * The RAF loop only runs while the hook is mounted (i.e. while the post
 * viewer is open), so the performance impact is negligible.
 */
const useActiveThumbnailRect = (
  cloneRef: RefObject<HTMLElement>,
  /** Changing this value (e.g. a new post) resets the loop. */
  dep: unknown,
): void => {
  const rafRef = useRef<number>(0);

  useEffect(() => {
    const tick = () => {
      const clone = cloneRef.current;
      const source = findVisibleActive();

      if (clone && source) {
        const r = source.getBoundingClientRect();
        const bgImage = source.style.backgroundImage || '';

        if (bgImage) {
          clone.style.display = 'block';
          clone.style.top = `${r.top}px`;
          clone.style.left = `${r.left}px`;
          clone.style.width = `${r.width}px`;
          clone.style.height = `${r.height}px`;
          clone.style.backgroundImage = bgImage;
          clone.style.borderRadius = getComputedStyle(source).borderRadius;
        } else {
          clone.style.display = 'none';
        }
      } else if (clone) {
        clone.style.display = 'none';
      }

      rafRef.current = requestAnimationFrame(tick);
    };

    rafRef.current = requestAnimationFrame(tick);

    return () => cancelAnimationFrame(rafRef.current);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [dep]);
};

export default useActiveThumbnailRect;
