import { AsyncLocalStorage, AsyncResource } from 'async_hooks';

interface RequestContext {
  requestedBy?: string;
  requestId?: string;
}

class RequestContextManager {
  private storage = new AsyncLocalStorage<RequestContext>();
  private contexts = new Map<string, RequestContext>();

  getContext(requestId?: string): RequestContext {
    if (requestId && this.contexts.has(requestId)) {
      return this.contexts.get(requestId)!;
    }
    return this.storage.getStore() || {};
  }

  getRequestedBy(requestId?: string): string | undefined {
    return this.getContext(requestId).requestedBy;
  }

  run<T>(context: RequestContext, fn: () => Promise<T> | T): Promise<T> {
    const requestId = context.requestId || `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

    this.contexts.set(requestId, {
      ...context,
      requestId,
    });

    return new Promise((resolve, reject) => {
      this.storage.run({ ...context, requestId }, async () => {
        const resource = new AsyncResource('RequestContext');
        try {
          const result = await resource.runInAsyncScope(fn);
          resolve(result);
        } catch (err) {
          reject(err);
        } finally {
          // 清理上下文
          this.contexts.delete(requestId);
        }
      });
    });
  }
}

export const context = new RequestContextManager();
