import { AuthError, FatalError, QuotaExhaustedError, RateLimitError, TransientError } from "./index.js";
//#region src/openai-compat.ts
function mapMessagesToOpenAi(messages) {
	return messages.map((message) => ({
		role: message.role,
		content: mapContentToOpenAi(message.content)
	}));
}
function mapContentToOpenAi(content) {
	if (typeof content === "string") return content;
	return content.map((block) => {
		if (block.type === "text") return {
			type: "text",
			text: block.text
		};
		const img = block.image;
		return {
			type: "image_url",
			image_url: { url: `data:${img.mediaType};base64,${img.data}` }
		};
	});
}
function mapOpenAiResponse(body, provider, model) {
	const choice = body.choices[0];
	return {
		content: choice?.message.content ?? "",
		model: body.model || model,
		provider,
		usage: {
			promptTokens: body.usage?.prompt_tokens ?? 0,
			completionTokens: body.usage?.completion_tokens ?? 0
		},
		finishReason: choice?.finish_reason ?? void 0
	};
}
function classifyOpenAiCompatError(status, message, provider) {
	if (status === 429) {
		if (/quota/i.test(message)) return new QuotaExhaustedError(message, provider);
		return new RateLimitError(message, provider);
	}
	if (status === 401 || status === 403) return new AuthError(message, provider);
	if (status >= 500) return new TransientError(message, provider);
	return new FatalError(message, provider);
}
function makeOpenAiCompatAdapter(creds) {
	const baseUrl = creds.baseUrl ?? "https://api.openai.com/v1";
	const fetchImpl = creds.fetch ?? fetch;
	return {
		provider: "openai-compat",
		supportsImage: true,
		async call(req) {
			const payload = {
				model: req.model,
				messages: mapMessagesToOpenAi(req.messages),
				...req.maxTokens !== void 0 ? { max_tokens: req.maxTokens } : {},
				...req.temperature !== void 0 ? { temperature: req.temperature } : {},
				...req.stop !== void 0 ? { stop: req.stop } : {}
			};
			const response = await fetchImpl(`${baseUrl}/chat/completions`, {
				method: "POST",
				headers: {
					Authorization: `Bearer ${creds.apiKey}`,
					"Content-Type": "application/json"
				},
				body: JSON.stringify(payload)
			});
			const text = await response.text();
			let body;
			try {
				body = JSON.parse(text);
			} catch {
				throw new TransientError(`Invalid JSON from provider: ${text.slice(0, 120)}`, "openai-compat");
			}
			if (!response.ok) {
				const message = typeof body === "object" && body !== null && "error" in body && typeof body.error?.message === "string" ? body.error.message : text;
				throw classifyOpenAiCompatError(response.status, message, "openai-compat");
			}
			return mapOpenAiResponse(body, "openai-compat", req.model);
		}
	};
}
//#endregion
export { classifyOpenAiCompatError, makeOpenAiCompatAdapter, mapContentToOpenAi, mapMessagesToOpenAi, mapOpenAiResponse };
