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

/**
 * useTimer — auto-cleaning setTimeout helper.
 *
 * Background
 * ──────────
 * `App.jsx` had two timer use cases (clear-canvas two-tap arming and toast
 * auto-dismiss) that each followed the same shape:
 *
 *     const timerRef = useRef(null);
 *     // schedule:
 *     if (timerRef.current) clearTimeout(timerRef.current);
 *     timerRef.current = setTimeout(() => { ...; timerRef.current = null }, ms);
 *     // unmount cleanup:
 *     useEffect(() => () => {
 *       if (timerRef.current) clearTimeout(timerRef.current);
 *     }, []);
 *
 * The same boilerplate, three side-effects (arm, cancel-and-rearm, cleanup),
 * one bug surface — forgetting any of them strands a timer or fails to
 * cancel a previous one. This hook collapses it to:
 *
 *     const timer = useTimer();
 *     timer.schedule(() => { ... }, 3000);  // auto-cancels any pending one
 *     timer.cancel();                       // explicit early cancellation
 *
 * Cleanup on unmount is automatic.
 *
 * Why not setInterval-style
 * ─────────────────────────
 * setTimeout is one-shot, which matches both current callers' semantics:
 * "after N ms unless something else cancels me first". An interval helper
 * would be a different shape — leaving it for when there's a second
 * caller that needs it.
 */
export function useTimer() {
  const idRef = useRef(null);

  const cancel = useCallback(() => {
    if (idRef.current !== null) {
      clearTimeout(idRef.current);
      idRef.current = null;
    }
  }, []);

  const schedule = useCallback((fn, ms) => {
    cancel();
    idRef.current = setTimeout(() => {
      idRef.current = null;
      fn();
    }, ms);
  }, [cancel]);

  // Unmount cleanup. Returning the cleanup directly from useEffect rather
  // than capturing `cancel` in deps because the ref-based cancel is
  // identity-stable, so the effect can run once on mount and once on
  // unmount.
  useEffect(() => () => cancel(), [cancel]);

  return { schedule, cancel };
}
