import { useEffect, useState, useRef } from 'react';
import { useErrorHandler } from '../../hooks/useErrorHandler';

interface LoadingState {
  source: string;
  startTime: number;
  duration: number;
}

const loadingStates = new Map<string, LoadingState>();
const listeners = new Set<(states: LoadingState[]) => void>();

export function trackLoading(source: string, isLoading: boolean) {
  if (isLoading) {
    loadingStates.set(source, {
      source,
      startTime: Date.now(),
      duration: 0,
    });
  } else {
    loadingStates.delete(source);
  }
  listeners.forEach(listener => {
    const states = Array.from(loadingStates.values()).map(s => ({
      ...s,
      duration: Date.now() - s.startTime,
    }));
    listener(states);
  });
}

export default function LoadingStateMonitor() {
  const [localLoadingStates, setLocalLoadingStates] = useState<LoadingState[]>([]);
  const { addError } = useErrorHandler('LoadingStateMonitor');
  const reportedStuckStates = useRef<Set<string>>(new Set());
  const addErrorRef = useRef(addError);

  // Keep addError ref updated
  useEffect(() => {
    addErrorRef.current = addError;
  }, [addError]);

  useEffect(() => {
    const updateStates = (statesFromListener: LoadingState[]) => {
      // Use states from listener (always provided by trackLoading)
      const states = statesFromListener.filter(s => s.duration < 60000); // Only show states less than 60 seconds old
      
      setLocalLoadingStates(states);

      // Detect stuck loading states (more than 5 seconds) - only report once per state
      const stuck = states.filter(s => s.duration > 5000 && !reportedStuckStates.current.has(s.source));
      if (stuck.length > 0) {
        stuck.forEach(state => {
          reportedStuckStates.current.add(state.source);
          // Use ref to avoid dependency issues
          addErrorRef.current(
            new Error(`Loading state stuck: ${state.source} (${(state.duration / 1000).toFixed(1)}s)`),
            'LoadingStateMonitor'
          );
        });
      }

      // Clean up reported states that are no longer stuck
      const noLongerStuck = Array.from(reportedStuckStates.current).filter(
        source => !states.find(s => s.source === source && s.duration > 5000)
      );
      noLongerStuck.forEach(source => reportedStuckStates.current.delete(source));
    };

    // Initial update from global Map
    const initialStates = Array.from(loadingStates.values()).map(s => ({
      ...s,
      duration: Date.now() - s.startTime,
    }));
    updateStates(initialStates);

    listeners.add(updateStates);

    // Periodic check (in case listener doesn't fire)
    const interval = setInterval(() => {
      const currentStates = Array.from(loadingStates.values()).map(s => ({
        ...s,
        duration: Date.now() - s.startTime,
      }));
      updateStates(currentStates);
    }, 1000);

    return () => {
      listeners.delete(updateStates);
      clearInterval(interval);
    };
  }, []); // Empty deps - updateStates reads from global Map via listeners

  // Auto-reset stuck loading states after 10 seconds
  useEffect(() => {
    const stuck = localLoadingStates.filter(s => s.duration > 10000);
    if (stuck.length > 0) {
      stuck.forEach(state => {
        console.warn(`Auto-resetting stuck loading state: ${state.source}`);
        trackLoading(state.source, false);
        reportedStuckStates.current.delete(state.source);
      });
    }
  }, [localLoadingStates]);

  return null; // This component doesn't render anything visible
}

