import { getLogger as getLogger$1 } from "../../../../logger.js";
import { createDefaultConversationHistoryConfig, formatMessagesAsConversationHistory, getConversationHistoryWithCompression } from "../../data/conversations.js";
import { fromBlobUri, getBlobStorageProvider, isBlobUri } from "../../services/blob-storage/index.js";
import { UnsupportedTextAttachmentSourceError } from "../../services/blob-storage/file-security-errors.js";
import { buildTextAttachmentBlock, decodeTextDocumentBytes, isTextDocumentMimeType } from "../../utils/text-document-attachments.js";
import { getPrimaryModel, getSummarizerModel } from "./model-config.js";
import { normalizeInlineFileBytes } from "../../services/blob-storage/file-content-security.js";
import { calculateBreakdownTotal, estimateTokens } from "@inkeep/agents-core";
import { normalizeMimeType } from "@inkeep/agents-core/constants/allowed-file-formats";

//#region src/domains/run/agents/generation/conversation-history.ts
const PDF_MEDIA_TYPE = "application/pdf";
const logger = getLogger$1("conversation-history");
function mapFileToAiSdkContentPart(fileValue, mimeType, metadata) {
	if (mimeType.startsWith("image/")) return {
		type: "image",
		image: fileValue,
		...metadata?.detail && { experimental_providerMetadata: { openai: { imageDetail: metadata.detail } } }
	};
	if (mimeType === PDF_MEDIA_TYPE) return {
		type: "file",
		data: fileValue,
		mediaType: PDF_MEDIA_TYPE,
		...metadata?.filename ? { filename: metadata.filename } : {}
	};
	return null;
}
async function buildConversationHistory(ctx, contextId, taskId, userMessage, streamRequestId, initialContextBreakdown) {
	let conversationHistory = "";
	const historyConfig = ctx.config.conversationHistoryConfig ?? createDefaultConversationHistoryConfig();
	if (historyConfig && historyConfig.mode !== "none") {
		if (historyConfig.mode === "full") {
			const filters = {
				delegationId: ctx.delegationId,
				isDelegated: ctx.isDelegatedAgent
			};
			conversationHistory = await formatMessagesAsConversationHistory(await getConversationHistoryWithCompression({
				tenantId: ctx.config.tenantId,
				projectId: ctx.config.projectId,
				conversationId: contextId,
				currentMessage: userMessage,
				options: historyConfig,
				filters,
				summarizerModel: getSummarizerModel(ctx.config),
				baseModel: getPrimaryModel(ctx.config),
				streamRequestId,
				fullContextSize: initialContextBreakdown.total
			}));
		} else if (historyConfig.mode === "scoped") conversationHistory = await formatMessagesAsConversationHistory(await getConversationHistoryWithCompression({
			tenantId: ctx.config.tenantId,
			projectId: ctx.config.projectId,
			conversationId: contextId,
			currentMessage: userMessage,
			options: historyConfig,
			filters: {
				subAgentId: ctx.config.id,
				taskId,
				delegationId: ctx.delegationId,
				isDelegated: ctx.isDelegatedAgent
			},
			summarizerModel: getSummarizerModel(ctx.config),
			baseModel: getPrimaryModel(ctx.config),
			streamRequestId,
			fullContextSize: initialContextBreakdown.total
		}));
	}
	const conversationHistoryTokens = estimateTokens(conversationHistory);
	const updatedContextBreakdown = {
		components: {
			...initialContextBreakdown.components,
			conversationHistory: conversationHistoryTokens
		},
		total: initialContextBreakdown.total
	};
	calculateBreakdownTotal(updatedContextBreakdown);
	return {
		conversationHistory,
		contextBreakdown: updatedContextBreakdown
	};
}
async function buildTextAttachmentPart(part, mimeType) {
	const filename = typeof part.metadata?.filename === "string" ? part.metadata.filename : void 0;
	const file = part.file;
	let content;
	if ("bytes" in file && file.bytes) content = decodeTextDocumentBytes((await normalizeInlineFileBytes(file)).data);
	else if ("uri" in file && file.uri && isBlobUri(file.uri)) {
		let downloaded;
		try {
			downloaded = await getBlobStorageProvider().download(fromBlobUri(file.uri));
		} catch (err) {
			logger.warn({
				err,
				uri: file.uri,
				mimeType,
				failureKind: "download"
			}, "Failed to download text attachment from blob storage");
			return {
				type: "text",
				text: buildTextAttachmentBlock({
					mimeType,
					content: "[Attachment unavailable]",
					filename
				})
			};
		}
		try {
			content = decodeTextDocumentBytes(downloaded.data);
		} catch (err) {
			logger.warn({
				err,
				uri: file.uri,
				mimeType,
				failureKind: "decode"
			}, "Failed to decode text attachment from blob storage");
			return {
				type: "text",
				text: buildTextAttachmentBlock({
					mimeType,
					content: "[Attachment unavailable]",
					filename
				})
			};
		}
	} else throw new UnsupportedTextAttachmentSourceError(mimeType);
	return {
		type: "text",
		text: buildTextAttachmentBlock({
			mimeType,
			content,
			filename
		})
	};
}
async function buildInitialMessages(systemPrompt, conversationHistory, userMessage, fileParts) {
	const messages = [];
	messages.push({
		role: "system",
		content: systemPrompt
	});
	if (conversationHistory.trim() !== "") messages.push({
		role: "user",
		content: conversationHistory
	});
	const userContent = await buildUserMessageContent(userMessage, fileParts);
	messages.push({
		role: "user",
		content: userContent
	});
	return messages;
}
async function buildUserMessageContent(text, fileParts) {
	if (!fileParts || fileParts.length === 0) return text;
	const content = [{
		type: "text",
		text
	}];
	for (const part of fileParts) {
		const file = part.file;
		const fileValue = "uri" in file && file.uri ? new URL(file.uri) : `data:${file.mimeType || ""};base64,${file.bytes}`;
		const mimeType = normalizeMimeType(file.mimeType ?? "");
		if (isTextDocumentMimeType(mimeType)) {
			content.push(await buildTextAttachmentPart(part, mimeType));
			continue;
		}
		const mappedPart = mapFileToAiSdkContentPart(fileValue, mimeType, {
			detail: typeof part.metadata?.detail === "string" ? part.metadata.detail : void 0,
			filename: typeof part.metadata?.filename === "string" ? part.metadata.filename : void 0
		});
		if (mappedPart) content.push(mappedPart);
		else logger.warn({
			mimeType,
			source: "user-message"
		}, "Dropping unsupported file content part");
	}
	return content;
}

//#endregion
export { buildConversationHistory, buildInitialMessages, buildUserMessageContent };