import { cliErrorMessage } from "../util/error"

/**
 * Aggregate Promise.allSettled results into a single Error that names every
 * failed endpoint, or return null when all fulfilled. Used at TUI bootstrap
 * boundaries so a single 4xx doesn't drown its parallel siblings as
 * unhandled rejections — every failure surfaces in one labeled message.
 */
export type LabeledSettled = {
  name: string
  result: PromiseSettledResult<unknown>
}

export function aggregateFailures(labeled: LabeledSettled[]): Error | null {
  const failed = labeled.filter(
    (x): x is { name: string; result: PromiseRejectedResult } => x.result.status === "rejected",
  )
  if (failed.length === 0) return null

  const reasons = Array.from(
    failed
      .map((f) => ({ name: f.name, message: reasonMessage(f.result.reason) }))
      .reduce((grouped, failure) => {
        grouped.set(failure.message, [...(grouped.get(failure.message) ?? []), failure.name])
        return grouped
      }, new Map<string, string[]>())
      .entries(),
  )
    .map(([message, names]) =>
      names.length === 1 ? `${names[0]}: ${message}` : `${message}\nAffected startup requests: ${names.join(", ")}`,
    )
    .join("; ")
  const summary = `${failed.length} of ${labeled.length} requests failed: ${reasons}`
  const err = new Error(summary)
  err.cause = { failures: failed.map((f) => ({ name: f.name, reason: f.result.reason })) }
  return err
}

function reasonMessage(reason: unknown): string {
  const formatted = cliErrorMessage(reason)
  if (formatted) return formatted

  if (reason instanceof Error) return reason.message
  if (typeof reason === "string") return reason
  if (reason && typeof reason === "object") {
    const obj = reason as { message?: unknown; name?: unknown }
    if (typeof obj.message === "string") return obj.message
    if (typeof obj.name === "string") return obj.name
  }
  return String(reason)
}
