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

/**
 * Edge 3.3: Hook to track and handle tab visibility changes
 * Provides utilities for components to handle tab switching during long-running operations
 *
 * @returns Object with visibility state and utilities
 *
 * @example
 * ```typescript
 * const { isVisible, whenVisible, whenHidden } = useTabVisibility();
 *
 * // Only execute when tab is visible
 * whenVisible(() => {
 *   updateUI();
 * });
 *
 * // Execute when tab becomes hidden
 * whenHidden(() => {
 *   pauseOperations();
 * });
 * ```
 */
export function useTabVisibility() {
  const [isVisible, setIsVisible] = useState(!document.hidden);
  const visibilityCallbacksRef = useRef<{
    onVisible: (() => void)[];
    onHidden: (() => void)[];
  }>({
    onVisible: [],
    onHidden: [],
  });

  useEffect(() => {
    const handleVisibilityChange = () => {
      const wasVisible = isVisible;
      const nowVisible = !document.hidden;
      setIsVisible(nowVisible);

      // Edge 3.3: Execute callbacks when visibility changes
      if (wasVisible && !nowVisible) {
        // Tab became hidden
        visibilityCallbacksRef.current.onHidden.forEach((callback) => {
          try {
            callback();
          } catch (error) {
            console.error('[useTabVisibility] Error in onHidden callback:', error);
          }
        });
      } else if (!wasVisible && nowVisible) {
        // Tab became visible
        visibilityCallbacksRef.current.onVisible.forEach((callback) => {
          try {
            callback();
          } catch (error) {
            console.error('[useTabVisibility] Error in onVisible callback:', error);
          }
        });
      }
    };

    document.addEventListener('visibilitychange', handleVisibilityChange);

    return () => {
      document.removeEventListener('visibilitychange', handleVisibilityChange);
    };
  }, [isVisible]);

  /**
   * Execute callback only when tab is visible
   */
  const whenVisible = useCallback((callback: () => void) => {
    if (isVisible) {
      callback();
    } else {
      // Store callback to execute when tab becomes visible
      visibilityCallbacksRef.current.onVisible.push(callback);
    }
  }, [isVisible]);

  /**
   * Execute callback when tab becomes hidden
   */
  const whenHidden = useCallback((callback: () => void) => {
    visibilityCallbacksRef.current.onHidden.push(callback);
  }, []);

  /**
   * Execute callback when tab becomes visible
   */
  const onVisible = useCallback((callback: () => void) => {
    visibilityCallbacksRef.current.onVisible.push(callback);
  }, []);

  /**
   * Remove callback from visibility handlers
   */
  const removeCallback = useCallback((callback: () => void) => {
    visibilityCallbacksRef.current.onVisible = visibilityCallbacksRef.current.onVisible.filter(
      (cb) => cb !== callback,
    );
    visibilityCallbacksRef.current.onHidden = visibilityCallbacksRef.current.onHidden.filter(
      (cb) => cb !== callback,
    );
  }, []);

  return {
    isVisible,
    whenVisible,
    whenHidden,
    onVisible,
    removeCallback,
  };
}
