import { logger } from "../util/logger.js";
import { generateId } from "../util/random.js";
import { MessageItemType, MessageState, MessageType } from "../api/types.js";
import { toRawIlinkUserIdForApi } from "../auth/weixin-account-id.js";
import { sendMessage } from "../api/api.js";
//#region extensions/weixin/src/messaging/send.ts
function generateClientId() {
	return generateId("weixin");
}
function resolveToUserIdForApi(sessionTo, override) {
	const o = override?.trim();
	if (o) return o;
	return toRawIlinkUserIdForApi(sessionTo);
}
/**
* Convert markdown-formatted model reply to plain text for Weixin delivery.
* Preserves newlines; strips markdown syntax.
*/
function markdownToPlainText(text) {
	let result = text;
	result = result.replace(/```[^\n]*\n?([\s\S]*?)```/g, (_, code) => code.trim());
	result = result.replace(/!\[[^\]]*\]\([^)]*\)/g, "");
	result = result.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1");
	result = result.replace(/^\|[\s:|-]+\|$/gm, "");
	result = result.replace(/^\|(.+)\|$/gm, (_, inner) => inner.split("|").map((cell) => cell.trim()).join("  "));
	result = result.replace(/\*\*([^*]+)\*\*/g, "$1");
	result = result.replace(/\*([^*]+)\*/g, "$1");
	result = result.replace(/__([^_]+)__/g, "$1");
	result = result.replace(/`([^`]+)`/g, "$1");
	return result.trim();
}
/** Build a SendMessageReq containing a single text message. */
function buildTextMessageReq(params) {
	const { toUserIdForApi, text, contextToken, clientId } = params;
	const item_list = text ? [{
		type: MessageItemType.TEXT,
		text_item: { text }
	}] : [];
	return { msg: {
		from_user_id: "",
		to_user_id: toUserIdForApi,
		client_id: clientId,
		message_type: MessageType.BOT,
		message_state: MessageState.FINISH,
		item_list: item_list.length ? item_list : void 0,
		context_token: contextToken ?? void 0
	} };
}
/**
* Send a plain text message downstream.
*/
async function sendMessageWeixin(params) {
	const { to, text, opts } = params;
	const apiTo = resolveToUserIdForApi(to, params.toUserIdForApi);
	if (!opts.contextToken) logger.warn(`sendMessageWeixin: contextToken missing for to=${to}, sending without context`);
	const clientId = generateClientId();
	const req = buildTextMessageReq({
		toUserIdForApi: apiTo,
		text,
		contextToken: opts.contextToken,
		clientId
	});
	try {
		await sendMessage({
			baseUrl: opts.baseUrl,
			token: opts.token,
			timeoutMs: opts.timeoutMs,
			routeTag: opts.routeTag,
			body: req
		});
	} catch (err) {
		logger.error(`sendMessageWeixin: failed sessionTo=${to} apiTo=${apiTo} clientId=${clientId} err=${String(err)}`);
		throw err;
	}
	return { messageId: clientId };
}
/**
* Send one or more MessageItems (optionally preceded by a text caption) downstream.
* Each item is sent as its own request so that item_list always has exactly one entry.
*/
async function sendMediaItems(params) {
	const { to, text, mediaItem, opts, label } = params;
	const apiTo = resolveToUserIdForApi(to, params.toUserIdForApi);
	const items = [];
	if (text) items.push({
		type: MessageItemType.TEXT,
		text_item: { text }
	});
	items.push(mediaItem);
	let lastClientId = "";
	/** Each request uses `opts.contextToken` (no per-bubble refresh). */
	for (const item of items) {
		lastClientId = generateClientId();
		const req = { msg: {
			from_user_id: "",
			to_user_id: apiTo,
			client_id: lastClientId,
			message_type: MessageType.BOT,
			message_state: MessageState.FINISH,
			item_list: [item],
			context_token: opts.contextToken ?? void 0
		} };
		try {
			await sendMessage({
				baseUrl: opts.baseUrl,
				token: opts.token,
				timeoutMs: opts.timeoutMs,
				routeTag: opts.routeTag,
				body: req
			});
		} catch (err) {
			logger.error(`${label}: failed sessionTo=${to} apiTo=${apiTo} clientId=${lastClientId} err=${String(err)}`);
			throw err;
		}
	}
	logger.info(`${label}: success sessionTo=${to} apiTo=${apiTo} clientId=${lastClientId}`);
	return { messageId: lastClientId };
}
/**
* Send an image message downstream using a previously uploaded file.
* Optionally include a text caption as a separate TEXT item before the image.
*
* ImageItem fields:
*   - media.encrypt_query_param: CDN download param
*   - media.aes_key: AES key, base64-encoded
*   - mid_size: original ciphertext file size
*/
async function sendImageMessageWeixin(params) {
	const { to, text, uploaded, opts, toUserIdForApi } = params;
	if (!opts.contextToken) logger.warn(`sendImageMessageWeixin: contextToken missing for to=${to}, sending without context`);
	logger.info(`sendImageMessageWeixin: to=${to} filekey=${uploaded.filekey} fileSize=${uploaded.fileSize} aeskey=present`);
	return sendMediaItems({
		to,
		toUserIdForApi,
		text,
		mediaItem: {
			type: MessageItemType.IMAGE,
			image_item: {
				media: {
					encrypt_query_param: uploaded.downloadEncryptedQueryParam,
					aes_key: Buffer.from(uploaded.aeskey).toString("base64"),
					encrypt_type: 1
				},
				mid_size: uploaded.fileSizeCiphertext
			}
		},
		opts,
		label: "sendImageMessageWeixin"
	});
}
/**
* Send a video message downstream using a previously uploaded file.
* VideoItem: media (CDN ref), video_size (ciphertext bytes).
* Includes an optional text caption sent as a separate TEXT item first.
*/
async function sendVideoMessageWeixin(params) {
	const { to, text, uploaded, opts, toUserIdForApi } = params;
	if (!opts.contextToken) logger.warn(`sendVideoMessageWeixin: contextToken missing for to=${to}, sending without context`);
	return sendMediaItems({
		to,
		toUserIdForApi,
		text,
		mediaItem: {
			type: MessageItemType.VIDEO,
			video_item: {
				media: {
					encrypt_query_param: uploaded.downloadEncryptedQueryParam,
					aes_key: Buffer.from(uploaded.aeskey).toString("base64"),
					encrypt_type: 1
				},
				video_size: uploaded.fileSizeCiphertext
			}
		},
		opts,
		label: "sendVideoMessageWeixin"
	});
}
/**
* Send a file attachment downstream using a previously uploaded file.
* FileItem: media (CDN ref), file_name, len (plaintext bytes as string).
* Includes an optional text caption sent as a separate TEXT item first.
*/
async function sendFileMessageWeixin(params) {
	const { to, text, fileName, uploaded, opts, toUserIdForApi } = params;
	if (!opts.contextToken) logger.warn(`sendFileMessageWeixin: contextToken missing for to=${to}, sending without context`);
	return sendMediaItems({
		to,
		toUserIdForApi,
		text,
		mediaItem: {
			type: MessageItemType.FILE,
			file_item: {
				media: {
					encrypt_query_param: uploaded.downloadEncryptedQueryParam,
					aes_key: Buffer.from(uploaded.aeskey).toString("base64"),
					encrypt_type: 1
				},
				file_name: fileName,
				len: String(uploaded.fileSize)
			}
		},
		opts,
		label: "sendFileMessageWeixin"
	});
}
//#endregion
export { markdownToPlainText, sendFileMessageWeixin, sendImageMessageWeixin, sendMessageWeixin, sendVideoMessageWeixin };

//# sourceMappingURL=send.js.map