import { logger } from "../shared/observability/logger.js";

/**
 * Orchestrator：并行下游编排 + 降级标记（对齐 02-architecture-design.md §1.2 + §9 #6）。
 *
 * 核心能力：
 * - Promise.allSettled 并行执行多个下游调用
 * - 任一失败时记录 warn 日志 + 标记 partial=true
 * - 失败的字段返回 null，其他字段正常返回
 *
 * P4 用 Promise.allSettled 降级；P6 引入 opossum 熔断器后，
 * Orchestrator 将先检查熔断器状态再决定是否调用。
 */

export interface OrchestrationFailure {
  key: string;
  error: unknown;
}

export interface OrchestrationResult {
  /** 各任务结果（失败的 key 值为 null） */
  results: Record<string, unknown>;
  /** 是否有部分失败 */
  partial: boolean;
  /** 失败详情 */
  failures: OrchestrationFailure[];
}

/**
 * 并行执行多个下游调用，部分失败容忍。
 *
 * @param tasks - key → Promise 的映射
 * @returns OrchestrationResult
 *
 * @example
 * ```ts
 * const result = await orchestrate({
 *   parent: iamClient.getUserInfo(id),
 *   children: iamClient.getChildrenByParent(id),
 * });
 * const parent = result.results.parent as UserInfoDto | null;
 * const children = result.results.children as ChildDto[] | null;
 * if (result.partial) { // 有部分失败 }
 * ```
 */
export async function orchestrate(
  tasks: Record<string, Promise<unknown>>,
): Promise<OrchestrationResult> {
  const entries = Object.entries(tasks);
  const settled = await Promise.allSettled(
    entries.map(([, promise]) => promise),
  );

  const results: Record<string, unknown> = {};
  const failures: OrchestrationFailure[] = [];

  entries.forEach(([key], index) => {
    const settledResult = settled[index];
    if (settledResult && settledResult.status === "fulfilled") {
      results[key] = settledResult.value;
    } else if (settledResult && settledResult.status === "rejected") {
      results[key] = null;
      const error = settledResult.reason;
      failures.push({ key, error });
      logger.warn({ key, err: error }, "Orchestrator: downstream call failed");
    }
  });

  return {
    results,
    partial: failures.length > 0,
    failures,
  };
}
