import { getLogger } from "./logger.js";

//#region src/utils/retry.ts
const logger = getLogger("retry");
async function retryWithBackoff(fn, opts = {}) {
	const { maxAttempts = 3, maxDelayMs = 4e3, label = "operation" } = opts;
	for (let attempt = 1; attempt <= maxAttempts; attempt++) try {
		return await fn();
	} catch (error) {
		const isTimeout = error.name === "AbortError";
		const status = error.status;
		if (!isTimeout && !(typeof status === "number" && status >= 500) && !(status === 429) || attempt === maxAttempts) throw error;
		const retryAfter = error.headers?.get?.("Retry-After");
		const retryAfterMs = retryAfter ? (Number(retryAfter) || 0) * 1e3 : 0;
		const baseDelay = Math.min(500 * 2 ** (attempt - 1), maxDelayMs);
		const delay = Math.max(baseDelay, retryAfterMs) + Math.random() * 100;
		logger.warn({
			attempt,
			maxAttempts,
			status,
			delay: Math.round(delay),
			label
		}, `Retrying ${label} after transient failure`);
		await new Promise((resolve) => setTimeout(resolve, delay));
	}
	throw new Error("Unreachable");
}

//#endregion
export { retryWithBackoff };