import { useEffect, useState } from 'react';

/**
 * Polling hook with cancellation. Re-fetches `fn` every `intervalMs`
 * until unmounted. Returns the latest data, error, and a setter to
 * force-refresh on demand.
 */
export function usePolling<T>(
  fn: () => Promise<T>,
  intervalMs: number,
  deps: unknown[] = [],
): { data: T | null; error: Error | null; loading: boolean; refetch: () => void } {
  const [data, setData] = useState<T | null>(null);
  const [error, setError] = useState<Error | null>(null);
  const [loading, setLoading] = useState(true);
  const [tick, setTick] = useState(0);

  useEffect(() => {
    let cancelled = false;
    async function run(): Promise<void> {
      try {
        const v = await fn();
        if (!cancelled) {
          setData(v);
          setError(null);
          setLoading(false);
        }
      } catch (err) {
        if (!cancelled) {
          setError(err as Error);
          setLoading(false);
        }
      }
    }
    void run();
    const id = setInterval(() => { void run(); }, intervalMs);
    return () => {
      cancelled = true;
      clearInterval(id);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [...deps, tick, intervalMs]);

  return {
    data,
    error,
    loading,
    refetch: () => setTick((t) => t + 1),
  };
}
