/**
 * 组件性能优化工具
 */
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue';
import type { Ref, ComputedRef, WatchStopHandle } from 'vue';

// 防抖函数
export function useDebounce<T extends (...args: any[]) => any>(
  fn: T,
  delay: number = 300
): [T, () => void] {
  let timeoutId: number | null = null;
  
  const debouncedFn = ((...args: any[]) => {
    if (timeoutId !== null) {
      clearTimeout(timeoutId);
    }
    
    timeoutId = window.setTimeout(() => {
      fn(...args);
      timeoutId = null;
    }, delay);
  }) as T;
  
  const cancel = () => {
    if (timeoutId !== null) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }
  };
  
  return [debouncedFn, cancel];
}

// 节流函数
export function useThrottle<T extends (...args: any[]) => any>(
  fn: T,
  delay: number = 300
): [T, () => void] {
  let lastExecTime = 0;
  let timeoutId: number | null = null;
  
  const throttledFn = ((...args: any[]) => {
    const now = Date.now();
    
    if (now - lastExecTime >= delay) {
      fn(...args);
      lastExecTime = now;
    } else {
      if (timeoutId !== null) {
        clearTimeout(timeoutId);
      }
      
      timeoutId = window.setTimeout(() => {
        fn(...args);
        lastExecTime = Date.now();
        timeoutId = null;
      }, delay - (now - lastExecTime));
    }
  }) as T;
  
  const cancel = () => {
    if (timeoutId !== null) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }
  };
  
  return [throttledFn, cancel];
}

// 虚拟滚动
export function useVirtualScroll<T>(
  items: Ref<T[]>,
  itemHeight: number,
  containerHeight: number,
  buffer: number = 5
) {
  const scrollTop = ref(0);
  const containerRef = ref<HTMLElement>();
  
  const visibleRange = computed(() => {
    const start = Math.floor(scrollTop.value / itemHeight);
    const end = Math.min(
      start + Math.ceil(containerHeight / itemHeight) + buffer,
      items.value.length
    );
    
    return {
      start: Math.max(0, start - buffer),
      end
    };
  });
  
  const visibleItems = computed(() => {
    const { start, end } = visibleRange.value;
    return items.value.slice(start, end).map((item, index) => ({
      item,
      index: start + index
    }));
  });
  
  const totalHeight = computed(() => items.value.length * itemHeight);
  
  const offsetY = computed(() => visibleRange.value.start * itemHeight);
  
  const handleScroll = useThrottle((event: Event) => {
    const target = event.target as HTMLElement;
    scrollTop.value = target.scrollTop;
  }, 16)[0]; // 60fps
  
  onMounted(() => {
    if (containerRef.value) {
      containerRef.value.addEventListener('scroll', handleScroll);
    }
  });
  
  onUnmounted(() => {
    if (containerRef.value) {
      containerRef.value.removeEventListener('scroll', handleScroll);
    }
  });
  
  return {
    containerRef,
    visibleItems,
    totalHeight,
    offsetY
  };
}

// 图片懒加载
export function useLazyImage() {
  const imageRef = ref<HTMLImageElement>();
  const isLoaded = ref(false);
  const isError = ref(false);
  const isIntersecting = ref(false);
  
  let observer: IntersectionObserver | null = null;
  
  const load = (src: string) => {
    if (!imageRef.value || isLoaded.value) return;
    
    const img = new Image();
    img.onload = () => {
      if (imageRef.value) {
        imageRef.value.src = src;
        isLoaded.value = true;
      }
    };
    img.onerror = () => {
      isError.value = true;
    };
    img.src = src;
  };
  
  onMounted(() => {
    if (imageRef.value) {
      observer = new IntersectionObserver(
        (entries) => {
          entries.forEach((entry) => {
            isIntersecting.value = entry.isIntersecting;
          });
        },
        { threshold: 0.1 }
      );
      
      observer.observe(imageRef.value);
    }
  });
  
  onUnmounted(() => {
    if (observer) {
      observer.disconnect();
    }
  });
  
  return {
    imageRef,
    isLoaded,
    isError,
    isIntersecting,
    load
  };
}

// 无限滚动
export function useInfiniteScroll<T>(
  loadMore: () => Promise<T[]>,
  options: {
    threshold?: number;
    initialLoad?: boolean;
  } = {}
) {
  const { threshold = 100, initialLoad = true } = options;
  
  const items = ref<T[]>([]);
  const loading = ref(false);
  const finished = ref(false);
  const error = ref<Error | null>(null);
  const containerRef = ref<HTMLElement>();
  
  const load = async () => {
    if (loading.value || finished.value) return;
    
    loading.value = true;
    error.value = null;
    
    try {
      const newItems = await loadMore();
      
      if (newItems.length === 0) {
        finished.value = true;
      } else {
        items.value.push(...newItems);
      }
    } catch (err) {
      error.value = err as Error;
    } finally {
      loading.value = false;
    }
  };
  
  const checkScroll = useThrottle(() => {
    if (!containerRef.value || loading.value || finished.value) return;
    
    const { scrollTop, scrollHeight, clientHeight } = containerRef.value;
    
    if (scrollTop + clientHeight >= scrollHeight - threshold) {
      load();
    }
  }, 100)[0];
  
  onMounted(() => {
    if (initialLoad) {
      load();
    }
    
    if (containerRef.value) {
      containerRef.value.addEventListener('scroll', checkScroll);
    }
  });
  
  onUnmounted(() => {
    if (containerRef.value) {
      containerRef.value.removeEventListener('scroll', checkScroll);
    }
  });
  
  const reset = () => {
    items.value = [];
    loading.value = false;
    finished.value = false;
    error.value = null;
  };
  
  return {
    items,
    loading,
    finished,
    error,
    containerRef,
    load,
    reset
  };
}

// 响应式断点
export function useBreakpoints() {
  const width = ref(window.innerWidth);
  const height = ref(window.innerHeight);
  
  const updateSize = useThrottle(() => {
    width.value = window.innerWidth;
    height.value = window.innerHeight;
  }, 100)[0];
  
  onMounted(() => {
    window.addEventListener('resize', updateSize);
  });
  
  onUnmounted(() => {
    window.removeEventListener('resize', updateSize);
  });
  
  const breakpoints = computed(() => ({
    xs: width.value < 576,
    sm: width.value >= 576 && width.value < 768,
    md: width.value >= 768 && width.value < 992,
    lg: width.value >= 992 && width.value < 1200,
    xl: width.value >= 1200 && width.value < 1600,
    xxl: width.value >= 1600
  }));
  
  return {
    width,
    height,
    breakpoints
  };
}

// 组件可见性检测
export function useVisibility(threshold: number = 0.1) {
  const elementRef = ref<HTMLElement>();
  const isVisible = ref(false);
  
  let observer: IntersectionObserver | null = null;
  
  onMounted(() => {
    if (elementRef.value) {
      observer = new IntersectionObserver(
        (entries) => {
          entries.forEach((entry) => {
            isVisible.value = entry.isIntersecting;
          });
        },
        { threshold }
      );
      
      observer.observe(elementRef.value);
    }
  });
  
  onUnmounted(() => {
    if (observer) {
      observer.disconnect();
    }
  });
  
  return {
    elementRef,
    isVisible
  };
}

// 长列表优化
export function useLongList<T>(
  data: Ref<T[]>,
  itemHeight: number = 50,
  visibleCount: number = 10
) {
  const scrollTop = ref(0);
  const containerRef = ref<HTMLElement>();
  
  const startIndex = computed(() => {
    return Math.floor(scrollTop.value / itemHeight);
  });
  
  const endIndex = computed(() => {
    return Math.min(startIndex.value + visibleCount, data.value.length);
  });
  
  const visibleData = computed(() => {
    return data.value.slice(startIndex.value, endIndex.value);
  });
  
  const paddingTop = computed(() => {
    return startIndex.value * itemHeight;
  });
  
  const paddingBottom = computed(() => {
    return (data.value.length - endIndex.value) * itemHeight;
  });
  
  const handleScroll = useThrottle((event: Event) => {
    const target = event.target as HTMLElement;
    scrollTop.value = target.scrollTop;
  }, 16)[0];
  
  onMounted(() => {
    if (containerRef.value) {
      containerRef.value.addEventListener('scroll', handleScroll);
    }
  });
  
  onUnmounted(() => {
    if (containerRef.value) {
      containerRef.value.removeEventListener('scroll', handleScroll);
    }
  });
  
  return {
    containerRef,
    visibleData,
    paddingTop,
    paddingBottom
  };
}

// 内存泄漏检测
export function useMemoryLeakDetection(componentName: string) {
  const watchers: WatchStopHandle[] = [];
  const timers: number[] = [];
  const listeners: Array<{ element: EventTarget; event: string; handler: EventListener }> = [];
  
  const addWatcher = (stopHandle: WatchStopHandle) => {
    watchers.push(stopHandle);
  };
  
  const addTimer = (timerId: number) => {
    timers.push(timerId);
  };
  
  const addListener = (element: EventTarget, event: string, handler: EventListener) => {
    element.addEventListener(event, handler);
    listeners.push({ element, event, handler });
  };
  
  onUnmounted(() => {
    // 清理 watchers
    watchers.forEach(stop => stop());
    
    // 清理 timers
    timers.forEach(id => clearTimeout(id));
    
    // 清理 listeners
    listeners.forEach(({ element, event, handler }) => {
      element.removeEventListener(event, handler);
    });
    
    console.log(`${componentName} 组件已清理完成`);
  });
  
  return {
    addWatcher,
    addTimer,
    addListener
  };
}
