import { lazy, Suspense } from 'react';
import LoadingSpinner from '@components/common/LoadingSpinner';

// Component cache to avoid re-creating lazy components
const componentCache = new Map();

/**
 * Higher-order component for lazy loading with error boundary and caching
 * @param {Function} importFunc - Dynamic import function
 * @param {Object} options - Configuration options
 * @returns {React.Component} Lazy loaded component with suspense
 */
export const lazyLoadComponent = (importFunc, options = {}) => {
  const {
    fallback = <LoadingSpinner />,
    errorFallback = <div>Error al cargar el componente</div>,
    retryCount = 3,
    retryDelay = 1000,
    cacheKey = importFunc.toString()
  } = options;

  // Return cached component if available
  if (componentCache.has(cacheKey)) {
    return componentCache.get(cacheKey);
  }

  const LazyComponent = lazy(() => {
    return new Promise((resolve, reject) => {
      let attempts = 0;
      
      const attemptImport = () => {
        attempts++;
        importFunc()
          .then((module) => {
            // Validate that the module has a default export
            if (!module.default) {
              throw new Error('Module does not have a default export');
            }
            resolve(module);
          })
          .catch((error) => {
            console.warn(`Lazy load attempt ${attempts} failed:`, error);
            if (attempts < retryCount) {
              setTimeout(attemptImport, retryDelay * attempts);
            } else {
              reject(error);
            }
          });
      };
      
      attemptImport();
    });
  });

  const LazyWrapper = function LazyWrapper(props) {
    return (
      <Suspense fallback={fallback}>
        <LazyComponent {...props} />
      </Suspense>
    );
  };

  // Cache the component
  componentCache.set(cacheKey, LazyWrapper);
  
  return LazyWrapper;
};

/**
 * Preload a lazy component with caching
 * @param {Function} importFunc - Dynamic import function
 * @param {string} cacheKey - Optional cache key
 */
export const preloadComponent = (importFunc, cacheKey = null) => {
  const key = cacheKey || importFunc.toString();
  
  // Check if already preloaded
  if (componentCache.has(`preload_${key}`)) {
    return componentCache.get(`preload_${key}`);
  }
  
  const componentImport = importFunc().catch(error => {
    console.warn('Preload failed:', error);
    return null;
  });
  
  // Cache the promise
  componentCache.set(`preload_${key}`, componentImport);
  
  return componentImport;
};

/**
 * Preload multiple components in parallel
 * @param {Array} importFuncs - Array of import functions
 */
export const preloadComponents = (importFuncs) => {
  return Promise.allSettled(
    importFuncs.map(importFunc => preloadComponent(importFunc))
  );
};

/**
 * Create a lazy route component with enhanced loading
 * @param {Function} importFunc - Dynamic import function
 * @param {Object} options - Configuration options
 * @returns {React.Component} Lazy route component
 */
export const createLazyRoute = (importFunc, options = {}) => {
  const {
    loadingMessage = 'Cargando módulo...',
    errorMessage = 'Error al cargar el módulo',
    ...lazyOptions
  } = options;

  return lazyLoadComponent(importFunc, {
    fallback: (
      <div className="lazy-route-loading">
        <LoadingSpinner />
        <p>{loadingMessage}</p>
      </div>
    ),
    errorFallback: (
      <div className="lazy-route-error">
        <p>{errorMessage}</p>
        <button onClick={() => window.location.reload()}>
          Reintentar
        </button>
      </div>
    ),
    ...lazyOptions
  });
};

/**
 * Intelligent preloading based on user interaction patterns
 */
export const intelligentPreload = {
  // Track user navigation patterns
  navigationHistory: [],
  
  // Preload based on likely next routes
  preloadLikelyRoutes(currentRoute) {
    const routeMap = {
      '/': ['/projects', '/field'],
      '/projects': ['/projects/new', '/field'],
      '/field': ['/projects'],
      '/reports': ['/projects']
    };
    
    const likelyRoutes = routeMap[currentRoute] || [];
    const importMap = {
      '/projects': () => import('@components/projects/ProjectList'),
      '/projects/new': () => import('@components/projects/ProjectForm'),
      '/field': () => import('@components/field/FieldApp'),
      '/reports': () => import('@components/reports/ReportDashboard')
    };
    
    likelyRoutes.forEach(route => {
      if (importMap[route]) {
        preloadComponent(importMap[route], route);
      }
    });
  },
  
  // Preload on hover with debouncing
  preloadOnHover(importFunc, delay = 200) {
    let timeoutId;
    
    return {
      onMouseEnter: () => {
        timeoutId = setTimeout(() => {
          preloadComponent(importFunc);
        }, delay);
      },
      onMouseLeave: () => {
        if (timeoutId) {
          clearTimeout(timeoutId);
        }
      }
    };
  }
};

// Pre-defined lazy components for heavy modules
export const LazyReportDashboard = createLazyRoute(() => 
  import('@components/reports/ReportDashboard')
);

export const LazyFieldApp = createLazyRoute(() => 
  import('@components/field/FieldApp')
);

export const LazyUserManagement = createLazyRoute(() => 
  import('@components/auth/UserManagement')
);

export const LazyProjectDetails = createLazyRoute(() => 
  import('@components/projects/ProjectDetails')
);

export const LazyRodalesManager = createLazyRoute(() => 
  import('@components/rodales/RodalesManager')
);