/* global React, ReactDOM */

// 17 Sep 2026 — useHoverPreview lives in its own EAGER file.
// It used to sit in GeneratePage.jsx, which index.html loads LAZILY (window.__loadLazyPage).
// Presentations and the Assets WIP tray call it too, so opening Presentations first on a fresh
// page crashed with "useHoverPreview is not defined". Canvas, the shot detail modal and Media
// called it only when window.useHoverPreview existed, so their hook order changed the moment
// Generate loaded. Loading it here, before every caller, fixes both. Callers call it
// unconditionally. test/lazyPageGlobals.test.js guards this.

// v07zz387 — Shared hover-to-enlarge preview (same mechanism the shot rail and
// asset-gen ref picker use). Renders a body-portaled .ga-hoverprev box (z 6000,
// pointer-events:none, floats above the ref modal) and positions it beside the
// hovered element on whichever side has more room, sized to the project's wide
// aspect. Usage: spread hoverBind(url) onto any tile + render {portal} once.
function useHoverPreview() {
  const hovRef = React.useRef(null);
  const hovImgRef = React.useRef(null);
  const hovTagRef = React.useRef(null);   // v07zz463 — GEN/REF badge for the in-place C-flick
  // v07zz424 — Hugo: open the floating preview only after the pointer RESTS on a
  // tile for 350ms (no fade — just a delay). A fresh hover, a mouseleave, or the
  // pointerdown/scroll auto-hide below all clear the pending open. timerRef holds it.
  const timerRef = React.useRef(null);
  const showHov = React.useCallback((url, el) => {
    const box = hovRef.current, img = hovImgRef.current;
    if (!box || !img || !url || !el) return;
    const src = window.thumbUrl ? window.thumbUrl(url, 1200) : url;   // v07zz424 — 1200 is allowlisted+pregenerated (1000 → 400 "bad width" on Railway cloud URLs → blank)
    if (img.getAttribute("src") !== src) img.setAttribute("src", src);   // preload during the delay
    if (hovTagRef.current) hovTagRef.current.textContent = "";   // v07zz463 — a fresh hover starts un-badged (on the image itself)
    const r = el.getBoundingClientRect();
    const vw = window.innerWidth, vh = window.innerHeight;
    const roomRight = vw - r.right - 14, roomLeft = r.left - 14;
    const toLeft = roomLeft > roomRight;
    const availW = Math.min(Math.max(320, toLeft ? roomLeft : roomRight), 1180);
    const boxH = Math.round(Math.min(900, vh * 0.86, availW * 9 / 21));
    box.style.height = boxH + "px"; box.style.maxWidth = availW + "px";
    const top = Math.min(Math.max(r.top + r.height / 2, boxH / 2 + 12), vh - boxH / 2 - 12);
    box.style.top = top + "px";
    if (toLeft) { box.style.left = "auto"; box.style.right = (vw - r.left + 14) + "px"; }
    else { box.style.right = "auto"; box.style.left = (r.right + 14) + "px"; }
    if (timerRef.current) clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => { if (hovRef.current) hovRef.current.style.display = "block"; }, 350);
  }, []);
  const hideHov = React.useCallback(() => {
    if (timerRef.current) { clearTimeout(timerRef.current); timerRef.current = null; }
    if (hovRef.current) hovRef.current.style.display = "none";
  }, []);
  const hoverBind = React.useCallback((url) => url ? ({ onMouseEnter: (e) => showHov(url, e.currentTarget), onMouseLeave: hideHov }) : {}, [showHov, hideHov]);
  // v07zz406 — Hugo: deleting/removing a hovered element (e.g. an active reference)
  // unmounts it WITHOUT firing mouseleave, so the floating preview got stuck on screen.
  // Hide it on any pointerdown (capture phase, so it runs BEFORE the delete click
  // handler) and on scroll — a fresh hover re-shows it. Fixes every useHoverPreview
  // consumer at once (refs picker, source frames, Sequence Shots modal).
  React.useEffect(() => {
    const hide = () => hideHov();
    document.addEventListener("pointerdown", hide, true);
    window.addEventListener("scroll", hide, true);
    return () => { document.removeEventListener("pointerdown", hide, true); window.removeEventListener("scroll", hide, true); if (timerRef.current) clearTimeout(timerRef.current); };
  }, [hideHov]);
  const portal = ReactDOM.createPortal(
    <div ref={hovRef} className="ga-hoverprev" style={{ display: "none" }} aria-hidden="true">
      <img ref={hovImgRef} alt="" />
      <span ref={hovTagRef} className="ga-hoverprev-tag"></span>
    </div>,
    document.body
  );
  // v07zz463 — expose imgRef + tagRef so a consumer can flick the floating preview IN PLACE
  // (e.g. shot gens: hover + press C → show the reference sent with that gen, inside the box).
  return { hoverBind, hideHov, portal, imgRef: hovImgRef, tagRef: hovTagRef };
}
// v07zz469 — cross-file export (no ES modules): Media's All Frames / Archived Frames
// galleries reuse the same hover-to-enlarge floating preview.
window.useHoverPreview = useHoverPreview;
