import { useEffect, useRef, useState } 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 smoothly-interpolated { x, y } offset for positioning irises
 * that lazily track the mouse cursor relative to an anchor point.
 *
 * 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 [offset, setOffset] = useState({ x: 0, y: 0 });
  const targetRef = useRef({ x: 0, y: 0 });
  const currentRef = useRef({ x: 0, y: 0 });
  const velocityRef = useRef({ x: 0, y: 0 });

  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;

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

      // Saccade: snap fast when target jumps significantly
      const e_ = dist > saccadeThreshold ? saccadeEase : ease;

      // Apply eased movement
      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;

      // Micro-drift: tiny organic tremor when nearly still
      if (dist < 0.1) {
        ec.x += (Math.random() - 0.5) * 0.02;
        ec.y += (Math.random() - 0.5) * 0.02;
      }

      setOffset({ x: ec.x, y: ec.y });
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);

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

  return offset;
}
