/**
 * Shared motion helpers — reduced-motion preference detection.
 *
 * Per WCAG 2.1 SC 2.3.3, autonomous motion (animations users didn't
 * explicitly initiate) must respect `prefers-reduced-motion: reduce`.
 * Traits that fire timer-driven or decorative animation should consult
 * `prefersReducedMotion()` in their setup() and either bail or render
 * a static fallback.
 *
 * User-initiated motion (drag, resize, toss, inertia) does NOT need
 * this guard — those traits respond to direct user input and are not
 * subject to the autonomous-animation rule.
 */

let cached = null;

export function prefersReducedMotion() {
  if (cached !== null) return cached;
  if (typeof window === 'undefined' || !window.matchMedia) {
    cached = false;
    return cached;
  }
  try {
    cached = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  } catch {
    cached = false;
  }
  return cached;
}

/**
 * Subscribe to reduced-motion changes — returns a cleanup fn.
 * Useful when a trait wants to switch behavior live as the user toggles
 * the OS preference.
 */
export function onReducedMotionChange(callback) {
  if (typeof window === 'undefined' || !window.matchMedia) return () => {};
  let mql;
  try {
    mql = window.matchMedia('(prefers-reduced-motion: reduce)');
  } catch {
    return () => {};
  }
  const handler = (e) => {
    cached = e.matches;
    callback(e.matches);
  };
  mql.addEventListener?.('change', handler);
  return () => mql.removeEventListener?.('change', handler);
}

/**
 * Test-only: reset the cached result so tests can mock matchMedia between cases.
 */
export function _resetMotionCache() {
  cached = null;
}
