// WebView 事件类型定义
const WebviewEvents = {
  /**
   * 获取平台信息
   */
  GET_PLATFORM: 'getPlatform',
  /**
   * 获取状态栏高度
   */
  GET_STATUS_BAR_HEIGHT: 'getStatusBarHeight',
  /**
   * 扫码
   */
  SCAN: 'scan',
  /**
   * 苹果支付
   */
  APPLE_PAY: 'applePay',
  APPLE_PAY_RESTORE: 'applePayRestore',
  /**
   * 微信是否安装
   */
  CHECK_WECHAT_INSTALLED: 'checkWechatInstalled',
  /**
   * 获取升级信息
   */
  GET_UPGRADE_INFO: 'getUpgradeInfo',
  /**
   * 下载升级
   */
  DOWNLOAD_UPGRADE: 'downloadAndInstall',
  /**
   * 打开 iframe
   */
  OPEN_IFRAME: 'openIframe'
} as const;

// 定义 WebView 事件键类型
type WebviewEventKey = keyof typeof WebviewEvents;
type WebviewEventValue = typeof WebviewEvents[WebviewEventKey];

// 定义 uni.webView 类型
interface UniWebView {
  postMessage: (options: {
    data: {
      action: string;
      data: {
        callbackAction: string;
        data?: any;
      };
    };
  }) => void;
}

// 扩展 uni 命名空间
declare global {
  interface Uni {
    webView?: UniWebView;
  }

  // 扩展 Window 接口
  interface Window {
    // 平台标识
    platform?: string;
    // WebView Bridge 实例
    webviewBridge: WebviewBridge;
    // 下载进度回调
    onDownloadProgress?: (progress: any) => void;
    // 动态回调函数
    [key: `webviewCallback_${string}`]: ((data: any) => void) | undefined;
  }
}

/**
 * 重置 window 回调函数
 * @param callbackEvent 回调事件名称
 */
function resetWindowCallback(callbackEvent: string): void {
  const key = callbackEvent as keyof Window;
  if (window[key]) {
    window[key] = undefined as never;
    delete window[key];
  }
}

/**
 * 获取 WebView 回调
 * @param event 事件名称
 * @param args 参数
 * @returns Promise
 */
async function getWebviewCallback<T = any>(
  event: string,
  args?: any
): Promise<T> {
  if (!uni.webView) {
    return Promise.reject(new Error('uni环境异常，请检查uni.webview是否正确引入'));
  }
  
  if (window.platform === 'h5') {
    return Promise.reject(new Error('请在app中使用'));
  }

  const callbackEvent = `webviewCallback_${event}`;
  
  try {
    return await new Promise<T>((resolve, reject) => {
      // 设置回调函数
      (window as any)[callbackEvent] = (data: T) => {
        resolve(data);
        resetWindowCallback(callbackEvent);
      };

      // 发送消息到 WebView
      uni.webView?.postMessage({
        data: {
          action: event,
          data: {
            callbackAction: callbackEvent,
            data: args
          }
        }
      });
    });
  } catch (error) {
    return Promise.reject(new Error('webview初始化失败，请检查是否正确引入uni.webview'));
  }
}

/**
 * WebView Bridge 类
 * 用于与原生 App 进行通信
 */
class WebviewBridge {
  constructor() {}

  /**
   * 获取平台信息
   * @returns Promise<string>
   */
  getPaltform(): Promise<string> {
    return getWebviewCallback<string>(WebviewEvents.GET_PLATFORM);
  }

  /**
   * 扫码功能
   * @param args 扫码参数
   * @returns Promise
   */
  scan(...args: any[]): Promise<any> {
    return getWebviewCallback(WebviewEvents.SCAN, args);
  }

  /**
   * 苹果支付
   * @param args 支付参数
   * @returns Promise
   */
  applePay(...args: any[]): Promise<any> {
    return getWebviewCallback(WebviewEvents.APPLE_PAY, args);
  }

  /**
   * 苹果支付恢复
   * @param args 恢复参数
   * @returns Promise
   */
  applePayRestore(...args: any[]): Promise<any> {
    return getWebviewCallback(WebviewEvents.APPLE_PAY_RESTORE, args);
  }

  /**
   * 检查微信是否已安装
   * @param args 参数
   * @returns Promise<boolean>
   */
  checkWechatInstalled(...args: any[]): Promise<boolean> {
    return getWebviewCallback<boolean>(WebviewEvents.CHECK_WECHAT_INSTALLED, args);
  }

  /**
   * 获取状态栏高度
   * @returns Promise<number>
   */
  getStatusBarHeight(): Promise<number> {
    return getWebviewCallback<number>(WebviewEvents.GET_STATUS_BAR_HEIGHT);
  }

  /**
   * 获取升级信息
   * @param args 参数
   * @returns Promise
   */
  getUpgradeInfo(...args: any[]): Promise<any> {
    return getWebviewCallback(WebviewEvents.GET_UPGRADE_INFO, args);
  }

  /**
   * 打开 iframe
   * @param args 参数
   * @returns Promise
   */
  openIframe(...args: any[]): Promise<any> {
    return getWebviewCallback(WebviewEvents.OPEN_IFRAME, args);
  }

  /**
   * 下载升级包
   * @param url 下载地址
   * @param progressCb 进度回调函数
   * @returns Promise
   */
  downloadUpgrade(url: string, progressCb?: (progress: any) => void): Promise<any> {
    if (progressCb) {
      window.onDownloadProgress = progressCb;
    }
    return getWebviewCallback(WebviewEvents.DOWNLOAD_UPGRADE, {
      url,
      progressCb: 'onDownloadProgress'
    });
  }
}

// 创建实例并挂载到 window
const webviewBridge = new WebviewBridge();
window.webviewBridge = webviewBridge;

export default webviewBridge;
export { WebviewBridge, WebviewEvents };

