import { useEffect, useRef, useCallback } from "react";

interface LazyEyesOptions {
  /** Reference point the eyes "live" at (viewport coords). Eyes look away from this toward the mouse. */
  anchorRef: React.RefObject<{ x: number; y: number } | null>;
  /** Max pixel shift for the iris (default 1.5) */
  maxShift?: number;
  /** Lerp ease factor 0–1 for slow drift (default 0.04) */
  ease?: number;
  /** Saccade threshold — when target jumps more than this, snap fast (default 0.8) */
  saccadeThreshold?: number;
  /** Fast ease for saccade snap (default 0.35) */
  saccadeEase?: number;
}

/**
 * Returns a register function to attach iris elements for direct DOM updates.
 * No React state is set per frame — transforms are applied directly.
 *
 * Movement model:
 * - Small mouse moves → slow, lazy drift (ease)
 * - Large jumps → quick saccade snap (saccadeEase), then settle
 * - Tiny random micro-drift to avoid perfectly still eyes
 */
export function useLazyEyes({
  anchorRef,
  maxShift = 1.5,
  ease = 0.04,
  saccadeThreshold = 0.8,
  saccadeEase = 0.35,
}: LazyEyesOptions) {
  const targetRef = useRef({ x: 0, y: 0 });
  const currentRef = useRef({ x: 0, y: 0 });
  const velocityRef = useRef({ x: 0, y: 0 });
  const irisesRef = useRef<Set<HTMLElement>>(new Set());
  const offsetRef = useRef({ x: 0, y: 0 });

  const registerIris = useCallback((el: HTMLElement | null) => {
    if (el) {
      irisesRef.current.add(el);
    }
  }, []);

  const unregisterIris = useCallback((el: HTMLElement | null) => {
    if (el) {
      irisesRef.current.delete(el);
    }
  }, []);

  useEffect(() => {
    const onMouseMove = (e: MouseEvent) => {
      const anchor = anchorRef.current;
      if (!anchor) return;
      const dx = e.clientX - anchor.x;
      const dy = e.clientY - anchor.y;
      const dist = Math.sqrt(dx * dx + dy * dy) || 1;
      targetRef.current = {
        x: (dx / dist) * maxShift,
        y: (dy / dist) * maxShift,
      };
    };

    window.addEventListener("mousemove", onMouseMove);

    let raf = 0;
    const tick = () => {
      const ec = currentRef.current;
      const et = targetRef.current;
      const vel = velocityRef.current;

      const dx = et.x - ec.x;
      const dy = et.y - ec.y;
      const dist = Math.sqrt(dx * dx + dy * dy);

      const e_ = dist > saccadeThreshold ? saccadeEase : ease;

      vel.x = vel.x * 0.6 + dx * e_ * 0.4;
      vel.y = vel.y * 0.6 + dy * e_ * 0.4;
      ec.x += vel.x;
      ec.y += vel.y;

      if (dist < 0.1) {
        ec.x += (Math.random() - 0.5) * 0.02;
        ec.y += (Math.random() - 0.5) * 0.02;
      }

      offsetRef.current.x = ec.x;
      offsetRef.current.y = ec.y;

      // Direct DOM updates — no React re-render
      for (const iris of irisesRef.current) {
        iris.style.transform = `translate(${ec.x}px, ${ec.y}px)`;
      }

      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);

    return () => {
      window.removeEventListener("mousemove", onMouseMove);
      cancelAnimationFrame(raf);
    };
  }, [anchorRef, maxShift, ease, saccadeThreshold, saccadeEase]);

  return { offsetRef, registerIris, unregisterIris };
}
