import React, { useEffect, useRef, useCallback, useMemo, useState } from 'react';
import { ExtendedDeviceInfo } from './real-time-device-monitor';
import { useGracefulDegradation } from './edge-case-handler';

// Performance optimization configuration
export interface PerformanceConfig {
  enableVirtualization: boolean;
  enableLazyLoading: boolean;
  enableMemoryManagement: boolean;
  enableRAFOptimization: boolean;
  enableComputationThrottling: boolean;
  enableGarbageCollection: boolean;
  maxCacheSize: number;
  memoryThreshold: number;
  throttleMs: number;
  virtualScrollBuffer: number;
}

const DEFAULT_PERFORMANCE_CONFIG: PerformanceConfig = {
  enableVirtualization: true,
  enableLazyLoading: true,
  enableMemoryManagement: true,
  enableRAFOptimization: true,
  enableComputationThrottling: true,
  enableGarbageCollection: true,
  maxCacheSize: 100,
  memoryThreshold: 0.8,
  throttleMs: 16, // 60fps
  virtualScrollBuffer: 5
};

// Performance metrics
export interface PerformanceMetrics {
  renderTime: number;
  updateCount: number;
  memoryUsage: number;
  frameRate: number;
  cacheHitRatio: number;
  gcCount: number;
  timestamp: number;
}

// Memory management utilities
class MemoryManager {
  private static instance: MemoryManager;
  private cache = new Map<string, any>();
  private maxSize: number;
  private accessOrder = new Map<string, number>();

  constructor(maxSize: number = 100) {
    this.maxSize = maxSize;
  }

  static getInstance(maxSize?: number): MemoryManager {
    if (!MemoryManager.instance) {
      MemoryManager.instance = new MemoryManager(maxSize);
    }
    return MemoryManager.instance;
  }

  set(key: string, value: any): void {
    // LRU eviction
    if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
      const oldestKey = [...this.accessOrder.entries()]
        .sort(([, a], [, b]) => a - b)[0][0];
      this.cache.delete(oldestKey);
      this.accessOrder.delete(oldestKey);
    }

    this.cache.set(key, value);
    this.accessOrder.set(key, Date.now());
  }

  get(key: string): any {
    if (this.cache.has(key)) {
      this.accessOrder.set(key, Date.now());
      return this.cache.get(key);
    }
    return undefined;
  }

  clear(): void {
    this.cache.clear();
    this.accessOrder.clear();
  }

  getStats() {
    return {
      size: this.cache.size,
      maxSize: this.maxSize,
      usage: this.cache.size / this.maxSize
    };
  }
}// Performance monitoring hook
export const usePerformanceOptimizer = (
  config: Partial<PerformanceConfig> = {},
  deviceInfo: ExtendedDeviceInfo
) => {
  const finalConfig = { ...DEFAULT_PERFORMANCE_CONFIG, ...config };
  const { shouldDisableFeature } = useGracefulDegradation(deviceInfo);
  
  const [metrics, setMetrics] = useState<PerformanceMetrics>({
    renderTime: 0,
    updateCount: 0,
    memoryUsage: 0,
    frameRate: 60,
    cacheHitRatio: 0,
    gcCount: 0,
    timestamp: Date.now()
  });

  const memoryManagerRef = useRef<MemoryManager>();
  const renderStartRef = useRef<number>(0);
  const frameCountRef = useRef<number>(0);
  const lastFrameTimeRef = useRef<number>(0);
  const rafIdRef = useRef<number>(0);

  // Initialize memory manager
  useEffect(() => {
    memoryManagerRef.current = MemoryManager.getInstance(finalConfig.maxCacheSize);
  }, [finalConfig.maxCacheSize]);

  // RAF-based frame rate monitoring
  const monitorFrameRate = useCallback(() => {
    const now = performance.now();
    frameCountRef.current++;
    
    if (lastFrameTimeRef.current) {
      const deltaTime = now - lastFrameTimeRef.current;
      const currentFPS = 1000 / deltaTime;
      
      setMetrics(prev => ({
        ...prev,
        frameRate: Math.round(currentFPS * 0.1 + prev.frameRate * 0.9), // Smooth average
        timestamp: Date.now()
      }));
    }
    
    lastFrameTimeRef.current = now;
    
    if (finalConfig.enableRAFOptimization && !shouldDisableFeature('performance-monitoring')) {
      rafIdRef.current = requestAnimationFrame(monitorFrameRate);
    }
  }, [finalConfig.enableRAFOptimization, shouldDisableFeature]);

  // Memory usage monitoring
  const checkMemoryUsage = useCallback(() => {
    if ('memory' in performance) {
      const memory = (performance as any).memory;
      const usage = memory.usedJSHeapSize / memory.totalJSHeapSize;
      
      setMetrics(prev => ({ ...prev, memoryUsage: usage }));
      
      // Trigger garbage collection if threshold exceeded
      if (usage > finalConfig.memoryThreshold && finalConfig.enableGarbageCollection) {
        memoryManagerRef.current?.clear();
        
        // Suggest manual GC if available (Chrome DevTools)
        if (typeof window !== 'undefined' && 'gc' in window) {
          (window as any).gc();
        }
        
        setMetrics(prev => ({ ...prev, gcCount: prev.gcCount + 1 }));
      }
    }
  }, [finalConfig.memoryThreshold, finalConfig.enableGarbageCollection]);

  // Render time measurement
  const measureRenderTime = useCallback(() => {
    renderStartRef.current = performance.now();
  }, []);

  const recordRenderTime = useCallback(() => {
    if (renderStartRef.current) {
      const renderTime = performance.now() - renderStartRef.current;
      setMetrics(prev => ({
        ...prev,
        renderTime,
        updateCount: prev.updateCount + 1
      }));
    }
  }, []);   // Throttled computation utility
  const throttledComputation = useCallback(
    (computation: () => void, delay: number = finalConfig.throttleMs) => {
      if (!finalConfig.enableComputationThrottling) {
        computation();
        return;
      }

      const throttleKey = computation.toString();
      const cached = memoryManagerRef.current?.get(`throttle_${throttleKey}`);
      
      if (cached && Date.now() - cached < delay) {
        return; // Skip computation
      }
      
      memoryManagerRef.current?.set(`throttle_${throttleKey}`, Date.now());
      computation();
    },
    [finalConfig.throttleMs, finalConfig.enableComputationThrottling]
  );

  // Cache utility with hit ratio tracking
  const cache = useMemo(() => ({
    get: (key: string) => {
      const hit = memoryManagerRef.current?.get(key);
      const stats = memoryManagerRef.current?.getStats();
      
      if (stats) {
        setMetrics(prev => ({
          ...prev,
          cacheHitRatio: hit ? (prev.cacheHitRatio * 0.9 + 0.1) : (prev.cacheHitRatio * 0.9)
        }));
      }
      
      return hit;
    },
    set: (key: string, value: any) => {
      memoryManagerRef.current?.set(key, value);
    },
    clear: () => {
      memoryManagerRef.current?.clear();
    }
  }), []);

  // Start monitoring
  useEffect(() => {
    if (!shouldDisableFeature('performance-monitoring')) {
      rafIdRef.current = requestAnimationFrame(monitorFrameRate);
      
      const memoryInterval = setInterval(checkMemoryUsage, 5000); // Check every 5s
      
      return () => {
        cancelAnimationFrame(rafIdRef.current);
        clearInterval(memoryInterval);
      };
    }
  }, [monitorFrameRate, checkMemoryUsage, shouldDisableFeature]);

  return {
    metrics,
    measureRenderTime,
    recordRenderTime,
    throttledComputation,
    cache,
    memoryManager: memoryManagerRef.current,
    isOptimized: !shouldDisableFeature('performance-monitoring')
  };
};

// Performance optimized component wrapper
interface PerformanceWrapperProps {
  children: React.ReactNode;
  config?: Partial<PerformanceConfig>;
  deviceInfo: ExtendedDeviceInfo;
  enableDebug?: boolean;
}

export const PerformanceWrapper: React.FC<PerformanceWrapperProps> = ({
  children,
  config,
  deviceInfo,
  enableDebug = false
}) => {
  const {
    metrics,
    measureRenderTime,
    recordRenderTime,
    isOptimized
  } = usePerformanceOptimizer(config, deviceInfo);

  useEffect(() => {
    measureRenderTime();
  });

  useEffect(() => {
    recordRenderTime();
  });

  return (
    <>
      {children}
      {enableDebug && process.env.NODE_ENV === 'development' && isOptimized && (
        <PerformanceDebugPanel metrics={metrics} />
      )}
    </>
  );
};// Performance debug panel
interface PerformanceDebugPanelProps {
  metrics: PerformanceMetrics;
}

const PerformanceDebugPanel: React.FC<PerformanceDebugPanelProps> = ({ metrics }) => {
  const [isExpanded, setIsExpanded] = useState(false);

  const getStatusColor = (value: number, thresholds: [number, number]) => {
    if (value < thresholds[0]) return '#00aa00'; // Good
    if (value < thresholds[1]) return '#ffbb00'; // Warning
    return '#ff4444'; // Critical
  };

  const formatMemory = (bytes: number) => {
    if (bytes < 1024) return `${bytes}B`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
    return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
  };

  return (
    <div style={{
      position: 'fixed',
      top: '10px',
      right: '10px',
      background: 'rgba(0, 0, 0, 0.9)',
      color: 'white',
      padding: '10px',
      borderRadius: '5px',
      fontSize: '12px',
      fontFamily: 'monospace',
      zIndex: 10002,
      minWidth: '250px',
      border: '2px solid #00aa00'
    }}>
      <div 
        style={{ 
          cursor: 'pointer', 
          display: 'flex', 
          justifyContent: 'space-between',
          alignItems: 'center',
          marginBottom: '5px'
        }}
        onClick={() => setIsExpanded(!isExpanded)}
      >
        <span style={{ fontWeight: 'bold' }}>Performance Monitor</span>
        <span>{isExpanded ? '▼' : '▶'}</span>
      </div>
      
      {isExpanded && (
        <div>
          <div style={{ marginBottom: '10px' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <span>FPS:</span>
              <span style={{ color: getStatusColor(metrics.frameRate, [30, 45]) }}>
                {metrics.frameRate.toFixed(1)}
              </span>
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <span>Render Time:</span>
              <span style={{ color: getStatusColor(metrics.renderTime, [16, 33]) }}>
                {metrics.renderTime.toFixed(2)}ms
              </span>
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <span>Memory Usage:</span>
              <span style={{ color: getStatusColor(metrics.memoryUsage, [0.7, 0.9]) }}>
                {(metrics.memoryUsage * 100).toFixed(1)}%
              </span>
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <span>Cache Hit Ratio:</span>
              <span style={{ color: getStatusColor(1 - metrics.cacheHitRatio, [0.3, 0.7]) }}>
                {(metrics.cacheHitRatio * 100).toFixed(1)}%
              </span>
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <span>Updates:</span>
              <span>{metrics.updateCount}</span>
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <span>GC Count:</span>
              <span>{metrics.gcCount}</span>
            </div>
          </div>
          
          <div style={{ 
            fontSize: '10px', 
            color: '#999',
            borderTop: '1px solid #333',
            paddingTop: '5px'
          }}>
            Last updated: {new Date(metrics.timestamp).toLocaleTimeString()}
          </div>
        </div>
      )}
    </div>
  );
};

// Virtualized list component for performance
interface VirtualizedListProps {
  items: any[];
  itemHeight: number;
  containerHeight: number;
  renderItem: (item: any, index: number) => React.ReactNode;
  overscan?: number;
}

export const VirtualizedList: React.FC<VirtualizedListProps> = ({
  items,
  itemHeight,
  containerHeight,
  renderItem,
  overscan = 5
}) => {
  const [scrollTop, setScrollTop] = useState(0);
  const containerRef = useRef<HTMLDivElement>(null);

  const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan);
  const endIndex = Math.min(
    items.length - 1,
    Math.floor((scrollTop + containerHeight) / itemHeight) + overscan
  );

  const visibleItems = items.slice(startIndex, endIndex + 1);
  const totalHeight = items.length * itemHeight;
  const offsetY = startIndex * itemHeight;

  const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
    setScrollTop(e.currentTarget.scrollTop);
  }, []);

  return (
    <div
      ref={containerRef}
      style={{
        height: containerHeight,
        overflow: 'auto',
        position: 'relative'
      }}
      onScroll={handleScroll}
    >
      <div style={{ height: totalHeight, position: 'relative' }}>
        <div style={{ transform: `translateY(${offsetY}px)` }}>
          {visibleItems.map((item, index) => (
            <div key={startIndex + index} style={{ height: itemHeight }}>
              {renderItem(item, startIndex + index)}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

// Lazy loaded component
interface LazyComponentProps {
  loader: () => Promise<React.ComponentType<any>>;
  fallback?: React.ComponentType;
  threshold?: number;
}

export const LazyComponent: React.FC<LazyComponentProps> = ({
  loader,
  fallback: Fallback = () => <div>Loading...</div>,
  threshold = 100
}) => {
  const [Component, setComponent] = useState<React.ComponentType<any> | null>(null);
  const [isVisible, setIsVisible] = useState(false);
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setIsVisible(true);
          observer.disconnect();
        }
      },
      { rootMargin: `${threshold}px` }
    );

    if (ref.current) {
      observer.observe(ref.current);
    }

    return () => observer.disconnect();
  }, [threshold]);

  useEffect(() => {
    if (isVisible && !Component) {
      loader().then(setComponent);
    }
  }, [isVisible, Component, loader]);

  return (
    <div ref={ref}>
      {Component ? <Component /> : <Fallback />}
    </div>
  );
};

export default PerformanceWrapper;