import { useSyncExternalStore, useRef, useCallback } from 'react';
import { getSecondsUntil } from '@/lib/countdown';

/**
 * React hook for live countdown. Returns seconds remaining (null if no end time).
 * Uses IntersectionObserver to pause when containerRef element is off-screen.
 */
export function useCountdown(
  isoEnd: string | null,
  containerRef?: React.RefObject<Element | null>,
): number | null {
  const stateRef = useRef({
    snapshot: null as number | null,
    visible: true,
    timeoutId: null as ReturnType<typeof setTimeout> | null,
    io: null as IntersectionObserver | null,
  });

  const getSnapshot = useCallback((): number | null => {
    if (!isoEnd) return null;
    return stateRef.current.snapshot;
  }, [isoEnd]);

  const subscribe = useCallback(
    (onStoreChange: () => void) => {
      const state = stateRef.current;

      if (!isoEnd) {
        return () => {};
      }

      state.visible = true;

      const clearTimer = () => {
        if (!state.timeoutId) return;
        clearTimeout(state.timeoutId);
        state.timeoutId = null;
      };

      const scheduleTick = (remaining: number) => {
        clearTimer();
        if (remaining <= 0) return;
        const delay = remaining > 3600 ? 60_000 : 1_000;
        state.timeoutId = setTimeout(() => {
          tick();
        }, delay);
      };

      const tick = () => {
        if (!state.visible) return;
        const remaining = getSecondsUntil(isoEnd);
        if (remaining !== state.snapshot) {
          state.snapshot = remaining;
          onStoreChange();
        }
        scheduleTick(remaining);
      };

      const initial = getSecondsUntil(isoEnd);
      if (initial !== state.snapshot) {
        state.snapshot = initial;
        onStoreChange();
      }

      scheduleTick(initial);

      if (containerRef?.current) {
        state.io = new IntersectionObserver(([e]) => {
          if (!e) return;
          state.visible = e.isIntersecting;
          if (e.isIntersecting) {
            tick();
          } else {
            clearTimer();
          }
        });
        state.io.observe(containerRef.current);
      }

      return () => {
        clearTimer();
        if (state.io) {
          state.io.disconnect();
          state.io = null;
        }
        state.snapshot = null;
      };
    },
    [isoEnd, containerRef],
  );

  return useSyncExternalStore(subscribe, getSnapshot, () => null);
}
