import { WECHAT_BASE_URL, WECHAT_BACKOFF_DELAY_MS, WECHAT_MAX_CONSECUTIVE_FAILURES, WECHAT_RETRY_DELAY_MS, WeChatMessageType, wechatUserIdsByWorkspace, } from './types.js';
import { formatLarkTitle, formatLarkContent } from './format.js';
import { persistWeChatUserIds, persistWeChatGetUpdatesBuf, sleep } from './helpers.js';
import { getWeChatUpdates, sendWeChatTextMessage, extractWeChatTextFromMessage, isDuplicateWeChatMessage, getWeChatContextToken, setWeChatContextToken, } from './wechat-api.js';
import { isBuiltInCommand, buildCommandResponse } from './bot-commands.js';
import { getConfiguredBotAgent, runBotAgent } from './bot-agent.js';
export class WeChatNotificationAdapter {
    workspace;
    running = false;
    credentials;
    getUpdatesBuf = '';
    constructor(workspace, settings) {
        this.workspace = workspace;
        const token = settings.wechat?.token?.trim();
        const baseUrl = settings.wechat?.baseUrl?.trim() || WECHAT_BASE_URL;
        const accountId = settings.wechat?.accountId?.trim();
        if (!token || !accountId) {
            throw new Error('WeChat login is required. Scan the QR code first.');
        }
        this.credentials = {
            token,
            baseUrl,
            accountId,
            userId: settings.wechat?.userId,
        };
        this.getUpdatesBuf = settings.wechat?.getUpdatesBuf ?? '';
        if (settings.wechat?.userIds?.length) {
            wechatUserIdsByWorkspace.set(workspace.id, new Set(settings.wechat.userIds));
        }
    }
    async start() {
        if (this.running)
            return;
        this.running = true;
        void this.pollLoop();
    }
    async stop() {
        this.running = false;
    }
    async send(envelope) {
        const userIds = wechatUserIdsByWorkspace.get(this.workspace.id);
        if (!userIds?.size)
            return;
        const text = [
            formatLarkTitle(envelope),
            '',
            formatLarkContent(envelope),
        ].filter(Boolean).join('\n');
        for (const userId of userIds) {
            await sendWeChatTextMessage(this.credentials.baseUrl, this.credentials.token, userId, text, getWeChatContextToken(this.workspace.id, userId));
        }
    }
    hasRecipients() {
        return Boolean(wechatUserIdsByWorkspace.get(this.workspace.id)?.size);
    }
    async pollLoop() {
        let failures = 0;
        while (this.running) {
            try {
                const resp = await getWeChatUpdates(this.credentials.baseUrl, this.credentials.token, this.getUpdatesBuf);
                if (resp.ret !== undefined && resp.ret !== 0) {
                    failures++;
                    console.error(`[notification] WeChat getupdates failed workspaceId=${this.workspace.id} ret=${resp.ret} errcode=${resp.errcode} errmsg=${resp.errmsg}`);
                    await sleep(failures >= WECHAT_MAX_CONSECUTIVE_FAILURES ? WECHAT_BACKOFF_DELAY_MS : WECHAT_RETRY_DELAY_MS);
                    if (failures >= WECHAT_MAX_CONSECUTIVE_FAILURES)
                        failures = 0;
                    continue;
                }
                failures = 0;
                if (resp.get_updates_buf && resp.get_updates_buf !== this.getUpdatesBuf) {
                    this.getUpdatesBuf = resp.get_updates_buf;
                    persistWeChatGetUpdatesBuf(this.workspace.id, this.getUpdatesBuf);
                }
                for (const msg of resp.msgs ?? []) {
                    await this.handleMessage(msg);
                }
            }
            catch (err) {
                failures++;
                console.error(`[notification] WeChat polling error workspaceId=${this.workspace.id}:`, err);
                await sleep(failures >= WECHAT_MAX_CONSECUTIVE_FAILURES ? WECHAT_BACKOFF_DELAY_MS : WECHAT_RETRY_DELAY_MS);
                if (failures >= WECHAT_MAX_CONSECUTIVE_FAILURES)
                    failures = 0;
            }
        }
    }
    async handleMessage(msg) {
        if (msg.message_type !== WeChatMessageType.USER)
            return;
        if (isDuplicateWeChatMessage(this.workspace.id, msg))
            return;
        const fromUser = msg.from_user_id;
        if (!fromUser)
            return;
        const userIds = wechatUserIdsByWorkspace.get(this.workspace.id) ?? new Set();
        userIds.add(fromUser);
        wechatUserIdsByWorkspace.set(this.workspace.id, userIds);
        persistWeChatUserIds(this.workspace.id, Array.from(userIds));
        if (msg.context_token) {
            setWeChatContextToken(this.workspace.id, fromUser, msg.context_token);
        }
        const text = extractWeChatTextFromMessage(msg).trim();
        if (!text)
            return;
        if (isBuiltInCommand(text)) {
            await this.reply(fromUser, await buildCommandResponse({
                defaultWorkspaceId: this.workspace.id,
                conversationId: `wechat:${fromUser}`,
                text,
            }));
            return;
        }
        const botAgent = getConfiguredBotAgent(this.workspace.id);
        if (!botAgent) {
            await this.reply(fromUser, '请先设置agent');
            return;
        }
        await this.reply(fromUser, `${botAgent.name} working...`);
        const reply = await runBotAgent(this.workspace.id, botAgent, text);
        await this.reply(fromUser, reply);
    }
    async reply(to, text) {
        await sendWeChatTextMessage(this.credentials.baseUrl, this.credentials.token, to, text, getWeChatContextToken(this.workspace.id, to));
    }
}
//# sourceMappingURL=wechat-adapter.js.map