import { createLogger } from "../utils/logger/index.js";
import { init_logger } from "../utils/logger.js";
import { mergeTtsConfigFromAppConfig } from "../voice/tts/merge-config.js";
import { maybeApplyTtsToPayload } from "../voice/tts/payload.js";
import "./internal-outbound.js";
import { deliverOutboundMessage } from "./outbound/deliver.js";
import { OutboundPersistStore } from "./outbound/persist-store.js";
//#region src/channels/outbound-sender.ts
init_logger();
const log = createLogger("ChannelOutboundSender");
var ChannelOutboundSender = class {
	opts;
	hooks;
	persistStore;
	constructor(opts) {
		this.opts = opts;
	}
	setHooks(hooks) {
		this.hooks = hooks;
	}
	enablePersistence(agentDir) {
		this.persistStore = new OutboundPersistStore(agentDir);
	}
	/**
	* Redeliver every queued outbound item (called after channels are started).
	* Best-effort — may duplicate if the prior send succeeded but ack did not
	* land on disk.
	*/
	async replayPending() {
		if (!this.persistStore) return;
		const pending = [...this.persistStore.peek()];
		for (const p of pending) try {
			await this.send(p.message, { skipPersist: true });
			this.persistStore.ack(p.id);
		} catch (err) {
			log.error({
				id: p.id,
				err
			}, "Failed to replay outbound message");
		}
	}
	async send(msg, options) {
		log.debug({
			type: msg.type,
			channel: msg.channel,
			chatId: msg.chat_id
		}, "Received outbound message");
		let processedMsg = await this.applyTtsIfNeeded(msg);
		const queueId = !options?.skipPersist && this.persistStore ? this.persistStore.enqueue(structuredClone(processedMsg)) : null;
		try {
			if (this.hooks) {
				const hookResult = await this.hooks.runMessageSending(processedMsg.chat_id, processedMsg.content ?? "", processedMsg.channel);
				if (!hookResult.send) {
					if (queueId) this.persistStore.ack(queueId);
					return;
				}
				processedMsg = {
					...processedMsg,
					content: hookResult.content ?? processedMsg.content
				};
			}
			if (processedMsg.channel === "__xopc_internal") {
				log.debug({ chatId: processedMsg.chat_id }, "Outbound dropped (internal session — not a real channel)");
				if (queueId) this.persistStore.ack(queueId);
				return;
			}
			const plugin = this.opts.registry.get(processedMsg.channel);
			if (!plugin?.outbound) {
				log.error({ channel: processedMsg.channel }, "Unknown channel or no outbound adapter");
				if (queueId) this.persistStore.ack(queueId);
				return;
			}
			const result = await deliverOutboundMessage({
				cfg: this.opts.getConfig(),
				plugin,
				processedMsg
			});
			if (this.hooks) {
				const err = result && !result.success ? result.error : void 0;
				await this.hooks.runMessageSent(processedMsg.chat_id, processedMsg.content ?? "", result?.success ?? false, err, processedMsg.channel);
			}
			if (!result) {
				if (queueId) this.persistStore.ack(queueId);
				return;
			}
			if (result.success) log.info({
				channel: processedMsg.channel,
				chatId: processedMsg.chat_id,
				messageId: result.messageId
			}, "Message sent");
			else log.error({
				channel: processedMsg.channel,
				chatId: processedMsg.chat_id,
				error: result.error
			}, "Failed to send message");
			if (queueId) this.persistStore.ack(queueId);
		} catch (err) {
			log.error({
				channel: processedMsg.channel,
				chatId: processedMsg.chat_id,
				err
			}, "Outbound send threw");
			if (!queueId) throw err;
		}
	}
	async applyTtsIfNeeded(msg) {
		if (msg.type && msg.type !== "message") return msg;
		if (!msg.content?.trim()) return msg;
		if (msg.mediaUrl) return msg;
		const cfg = this.opts.getConfig();
		const ttsConfig = mergeTtsConfigFromAppConfig(cfg.messages?.tts);
		if (!ttsConfig.enabled) return msg;
		const inboundAudio = msg.metadata?.transcribedVoice === true;
		return maybeApplyTtsToPayload(msg, {
			config: ttsConfig,
			channel: msg.channel,
			inboundAudio,
			appConfig: cfg
		});
	}
};
//#endregion
export { ChannelOutboundSender };

//# sourceMappingURL=outbound-sender.js.map