/**
 * @file WorkerBridge - Web Worker 并行处理框架
 * @description 提供基于 Promise 的 Worker 通信接口，支持超时和错误处理
 * @module core/utils/worker
 */

/**
 * Worker 消息格式
 */
export type WorkerMessage<T = any> = {
  type: string;
  payload: T;
  id: string;
};

/**
 * Worker 响应格式
 */
export type WorkerResponse<T = any> = {
  type: string;
  payload: T;
  error?: string;
  id: string;
};

/**
 * WorkerBridge - 基于 Promise 的 Worker 通信桥接器
 *
 * 提供简洁的 Worker 消息发送接口，自动处理请求-响应匹配、超时和错误
 *
 * @example
 * ```typescript
 * const bridge = new WorkerBridge('/workers/face-detect.worker.ts');
 * await bridge.load();
 * const result = await bridge.post('detect', { imageData });
 * bridge.terminate();
 * ```
 */
export class WorkerBridge<TReq = any, TRes = any> {
  private _worker: Worker | null = null;
  private _pending: Map<string, { resolve: Function; reject: Function }> = new Map();
  private _url: string;

  /**
   * 创建 WorkerBridge
   * @param workerUrl Worker 文件 URL
   */
  constructor(workerUrl: string) {
    this._url = workerUrl;
  }

  /**
   * 加载 Worker
   */
  async load(): Promise<void> {
    this._worker = new Worker(this._url);
    this._worker.onmessage = (e: MessageEvent<WorkerResponse<TRes>>) => {
      const { id, payload, error } = e.data;
      const handlers = this._pending.get(id);
      if (handlers) {
        if (error) {
          handlers.reject(new Error(error));
        } else {
          handlers.resolve(payload);
        }
        this._pending.delete(id);
      }
    };
    this._worker.onerror = (e) => {
      // 将 Worker 错误广播给所有 pending 的 Promise
      for (const [id, handlers] of this._pending) {
        handlers.reject(new Error(`Worker error: ${e.message}`));
        this._pending.delete(id);
      }
    };
  }

  /**
   * 发送消息到 Worker 并等待响应
   *
   * @param type 消息类型
   * @param payload 消息载荷
   * @returns 响应 Promise
   * @throws 如果 Worker 未加载则抛出错误
   */
  async post(type: string, payload: TReq): Promise<TRes> {
    if (!this._worker) {
      throw new Error('Worker not loaded');
    }
    const id = crypto.randomUUID();
    return new Promise((resolve, reject) => {
      this._pending.set(id, { resolve, reject });
      this._worker!.postMessage({ type, payload, id } as WorkerMessage<TReq>);
      // 超时 30s
      setTimeout(() => {
        if (this._pending.has(id)) {
          this._pending.delete(id);
          reject(new Error('Worker timeout'));
        }
      }, 30000);
    });
  }

  /**
   * 终止 Worker
   */
  terminate(): void {
    this._worker?.terminate();
    this._worker = null;
    // 拒绝所有 pending 的 Promise
    for (const [, handlers] of this._pending) {
      handlers.reject(new Error('Worker terminated'));
    }
    this._pending.clear();
  }

  /**
   * 检查 Worker 是否已加载
   */
  get isLoaded(): boolean {
    return this._worker !== null;
  }

  /**
   * 获取当前 pending 请求数
   */
  get pendingCount(): number {
    return this._pending.size;
  }
}