/**
 * 组件懒加载工具
 */
import { defineAsyncComponent, Component } from 'vue';
import { LoadingOutlined } from '@ant-design/icons-vue';
import { h } from 'vue';

// 加载状态组件
const LoadingComponent = {
  setup() {
    return () =>
      h(
        'div',
        {
          style: {
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            minHeight: '200px',
            fontSize: '16px',
            color: '#999'
          }
        },
        [h(LoadingOutlined, { style: { marginRight: '8px' } }), '加载中...']
      );
  }
};

// 错误状态组件
const ErrorComponent = {
  props: ['error'],
  setup(props: { error: Error }) {
    return () =>
      h(
        'div',
        {
          style: {
            display: 'flex',
            flexDirection: 'column',
            justifyContent: 'center',
            alignItems: 'center',
            minHeight: '200px',
            padding: '20px',
            color: '#ff4d4f',
            backgroundColor: '#fff2f0',
            border: '1px solid #ffccc7',
            borderRadius: '6px'
          }
        },
        [
          h(
            'div',
            { style: { fontSize: '16px', marginBottom: '8px' } },
            '组件加载失败'
          ),
          h(
            'div',
            { style: { fontSize: '12px', color: '#999' } },
            props.error.message
          ),
          h(
            'button',
            {
              style: {
                marginTop: '12px',
                padding: '4px 12px',
                border: '1px solid #d9d9d9',
                borderRadius: '4px',
                backgroundColor: '#fff',
                cursor: 'pointer'
              },
              onClick: () => window.location.reload()
            },
            '重新加载'
          )
        ]
      );
  }
};

// 懒加载配置选项
interface LazyLoadOptions {
  loading?: Component;
  error?: Component;
  delay?: number;
  timeout?: number;
  retries?: number;
  retryDelay?: number;
}

// 默认配置
const defaultOptions: LazyLoadOptions = {
  loading: LoadingComponent,
  error: ErrorComponent,
  delay: 200,
  timeout: 30000,
  retries: 3,
  retryDelay: 1000
};

/**
 * 创建懒加载组件
 * @param loader 组件加载函数
 * @param options 配置选项
 */
export function createLazyComponent(
  loader: () => Promise<any>,
  options: LazyLoadOptions = {}
) {
  const config = { ...defaultOptions, ...options };

  return defineAsyncComponent({
    loader: createRetryLoader(loader, config.retries!, config.retryDelay!),
    loadingComponent: config.loading,
    errorComponent: config.error,
    delay: config.delay,
    timeout: config.timeout
  });
}

/**
 * 创建带重试机制的加载器
 */
function createRetryLoader(
  loader: () => Promise<any>,
  retries: number,
  retryDelay: number
) {
  return async () => {
    let lastError: Error;

    for (let i = 0; i <= retries; i++) {
      try {
        return await loader();
      } catch (error) {
        lastError = error as Error;

        if (i < retries) {
          await new Promise((resolve) => setTimeout(resolve, retryDelay));
          console.warn(`组件加载失败，正在重试 (${i + 1}/${retries}):`, error);
        }
      }
    }

    throw lastError!;
  };
}

/**
 * 路由懒加载
 */
export function lazyRoute(
  loader: () => Promise<any>,
  options?: LazyLoadOptions
) {
  return createLazyComponent(loader, {
    ...options,
    loading: options?.loading || {
      setup() {
        return () =>
          h(
            'div',
            {
              style: {
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                minHeight: '60vh',
                fontSize: '16px',
                color: '#999'
              }
            },
            [
              h(LoadingOutlined, { style: { marginRight: '8px' } }),
              '页面加载中...'
            ]
          );
      }
    }
  });
}

/**
 * 模态框懒加载
 */
export function lazyModal(
  loader: () => Promise<any>,
  options?: LazyLoadOptions
) {
  return createLazyComponent(loader, {
    ...options,
    loading: options?.loading || {
      setup() {
        return () =>
          h(
            'div',
            {
              style: {
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                minHeight: '300px',
                fontSize: '14px',
                color: '#999'
              }
            },
            [h(LoadingOutlined, { style: { marginRight: '8px' } }), '加载中...']
          );
      }
    }
  });
}

/**
 * 图表懒加载
 */
export function lazyChart(
  loader: () => Promise<any>,
  options?: LazyLoadOptions
) {
  return createLazyComponent(loader, {
    ...options,
    loading: options?.loading || {
      setup() {
        return () =>
          h(
            'div',
            {
              style: {
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                minHeight: '400px',
                backgroundColor: '#fafafa',
                border: '1px dashed #d9d9d9',
                borderRadius: '6px',
                fontSize: '14px',
                color: '#999'
              }
            },
            [
              h(LoadingOutlined, { style: { marginRight: '8px' } }),
              '图表加载中...'
            ]
          );
      }
    }
  });
}

/**
 * 预加载组件
 */
export class ComponentPreloader {
  private preloadedComponents = new Map<string, Promise<any>>();

  /**
   * 预加载组件
   */
  preload(key: string, loader: () => Promise<any>) {
    if (!this.preloadedComponents.has(key)) {
      this.preloadedComponents.set(key, loader());
    }
    return this.preloadedComponents.get(key)!;
  }

  /**
   * 获取预加载的组件
   */
  get(key: string) {
    return this.preloadedComponents.get(key);
  }

  /**
   * 清除预加载的组件
   */
  clear(key?: string) {
    if (key) {
      this.preloadedComponents.delete(key);
    } else {
      this.preloadedComponents.clear();
    }
  }

  /**
   * 批量预加载
   */
  batchPreload(components: Record<string, () => Promise<any>>) {
    Object.entries(components).forEach(([key, loader]) => {
      this.preload(key, loader);
    });
  }
}

// 全局预加载器实例
export const componentPreloader = new ComponentPreloader();

/**
 * 智能懒加载 - 根据网络状况调整策略
 */
export function smartLazyComponent(
  loader: () => Promise<any>,
  options: LazyLoadOptions = {}
) {
  // 检测网络状况
  const connection = (navigator as any).connection;
  const isSlowNetwork =
    connection &&
    (connection.effectiveType === 'slow-2g' ||
      connection.effectiveType === '2g' ||
      connection.saveData);

  // 根据网络状况调整配置
  const smartOptions = {
    ...options,
    timeout: isSlowNetwork ? 60000 : options.timeout || 30000,
    retries: isSlowNetwork ? 5 : options.retries || 3,
    retryDelay: isSlowNetwork ? 2000 : options.retryDelay || 1000
  };

  return createLazyComponent(loader, smartOptions);
}

/**
 * 可见性懒加载 - 只有当组件进入视口时才加载
 */
export function visibilityLazyComponent(
  loader: () => Promise<any>,
  options: LazyLoadOptions = {}
) {
  return defineAsyncComponent({
    loader: () => {
      return new Promise((resolve, reject) => {
        const observer = new IntersectionObserver((entries) => {
          if (entries[0].isIntersecting) {
            observer.disconnect();
            loader().then(resolve).catch(reject);
          }
        });

        // 创建一个占位元素来观察
        const placeholder = document.createElement('div');
        document.body.appendChild(placeholder);
        observer.observe(placeholder);

        // 清理函数
        setTimeout(() => {
          observer.disconnect();
          document.body.removeChild(placeholder);
          reject(new Error('Visibility timeout'));
        }, options.timeout || 30000);
      });
    },
    loadingComponent: options.loading || LoadingComponent,
    errorComponent: options.error || ErrorComponent,
    delay: options.delay || 200
  });
}
