import { getLogger } from "../../../util/logger.js";
import { OperationQueue } from "../../../util/operation-queue.js";
import { sanitizeAiProviderResponse } from "../../chat/utils.js";
const peerQueue = (clark) => {
    const queue = clark.context.peerChannelQueue ?? new OperationQueue();
    clark.updateContext({
        peerChannelQueue: queue,
    });
    return (operation, delay = 0) => {
        if (delay) {
            return queue.enqueue(() => new Promise((resolve) => {
                setTimeout(() => {
                    void operation().then(resolve);
                }, delay);
            }));
        }
        else {
            return queue.enqueue(operation);
        }
    };
};
export const sendInteractiveMessageChannel = (clark, chatSessionStore) => {
    const sendUserMessage = sendUserMessageChannel(clark, chatSessionStore);
    return async (payload, delay = 0, immediate = false) => {
        if (clark.context.activeInteractiveMessage) {
            return {
                success: false,
                message: "Cannot send interactive message: there is already an active message that requires user input",
            };
        }
        const messageId = payload.id ?? crypto.randomUUID();
        const payloadWithId = { ...payload, id: messageId };
        clark.updateContext({
            activeInteractiveMessage: {
                id: messageId,
                payload: payloadWithId,
            },
        });
        await sendUserMessage(payloadWithId, delay, immediate);
        return {
            success: true,
        };
    };
};
export const sendUserMessageChannel = (clark, chatSessionStore) => {
    const queue = peerQueue(clark);
    return async (payload, delay = 0, immediate = false, { persistBeforeDeliver = false } = {}) => {
        // Generate ID upfront so both backend storage and frontend receive same ID
        const messageId = payload.id ?? crypto.randomUUID();
        const payloadWithId = {
            ...payload,
            id: messageId,
            content: sanitizeAiProviderResponse(payload.content) ?? "",
        };
        const deliver = async () => {
            if (persistBeforeDeliver) {
                try {
                    await chatSessionStore.recordAssistant(payloadWithId);
                }
                catch (err) {
                    getLogger().warn(`[ai-service] recordAssistant failed; continuing with peer delivery. type=${payloadWithId.type}`, err);
                }
            }
            else {
                void chatSessionStore.recordAssistant(payloadWithId);
            }
            if (!clark.context.peer) {
                getLogger().warn(`[ai-service] Cannot send message: no peer. type=${payloadWithId.type}, state=${clark.state}`);
                return;
            }
            return clark.context.peer.call.aiPushMessage(payloadWithId);
        };
        return immediate ? deliver() : queue(deliver, delay);
    };
};
export const sendUserGenerationStateChannel = (clark) => {
    return async (payload) => {
        // Store generation state in context for replay on reconnect
        clark.updateContext({
            lastGenerationState: {
                state: payload.state,
                hasSuggestions: payload.hasSuggestions,
            },
        });
        if (!clark.context.peer) {
            getLogger().warn(`[ai-service] Cannot send generation state: no peer. state=${payload.state}`);
            return;
        }
        return clark.context.peer.call.aiSetGenerationState(payload);
    };
};
/**
 * Clears the pendingToolPermissionRequest from the FSM context and notifies the
 * UI so it removes any stale permission prompt from the chat.
 */
export const clearPendingToolPermissionRequest = (clark) => {
    if (!clark.context.pendingToolPermissionRequest) {
        return;
    }
    clark.updateContext({
        pendingToolPermissionRequest: undefined,
    });
    if (!clark.context.peer) {
        getLogger().warn(`[ai-service] Cannot notify UI of cleared tool permission: no peer`);
        return;
    }
    void clark.context.peer.call.aiClearToolPermission().catch((err) => {
        getLogger().warn(`[ai-service] Failed to notify UI of cleared tool permission`, err);
    });
};
export const sendChangeInfoChannel = (clark, chatSessionStore) => {
    const queue = peerQueue(clark);
    return async (payload, delay = 0) => {
        return queue(async () => {
            void chatSessionStore.recordAssistantChangeInfo(payload);
            if (!clark.context.peer) {
                getLogger().warn(`[ai-service] Cannot send change info: no peer`);
                return;
            }
            return clark.context.peer.call.aiPushChangeInfo(payload);
        }, delay);
    };
};
//# sourceMappingURL=peer.js.map