export function normalizeChannelProvider(provider) {
    const normalized = provider.trim().toLowerCase();
    if (!normalized) {
        throw new Error('Channel provider is required.');
    }
    if (normalized === 'slack')
        return 'slack';
    if (normalized === 'telegram')
        return 'telegram';
    if (normalized === 'feishu' || normalized === 'lark' || normalized === 'feishu-lark')
        return 'feishu-lark';
    throw new Error(`Unsupported channel provider: ${provider}`);
}
export function buildChannelConversationKey(input) {
    const provider = normalizeChannelProvider(input.provider);
    const segments = [provider];
    if (input.workspaceId)
        segments.push(`workspace:${input.workspaceId.trim()}`);
    segments.push(`conversation:${input.conversationId.trim()}`);
    return segments.join('|');
}
export function buildChannelThreadKey(input) {
    const conversationKey = buildChannelConversationKey(input);
    const threadSegment = (input.threadId ?? input.messageId ?? input.conversationId).trim();
    return `${conversationKey}|thread:${threadSegment}`;
}
export function mapChannelThread(input) {
    const provider = normalizeChannelProvider(input.provider);
    const conversationId = input.conversationId.trim();
    if (!conversationId) {
        throw new Error('Channel conversationId is required.');
    }
    const threadId = (input.threadId ?? input.messageId ?? conversationId).trim();
    if (!threadId) {
        throw new Error('Channel threadId or messageId is required when conversationId is empty.');
    }
    return {
        provider,
        providerAlias: input.provider.trim().toLowerCase(),
        conversationId,
        threadId,
        messageId: input.messageId?.trim() || undefined,
        parentMessageId: input.parentMessageId?.trim() || undefined,
        workspaceId: input.workspaceId?.trim() || undefined,
        target: {
            kind: input.target.kind,
            id: input.target.id.trim(),
        },
        threadKey: buildChannelThreadKey({ ...input, provider, threadId }),
        conversationKey: buildChannelConversationKey({ ...input, provider }),
        sourceUrl: input.sourceUrl?.trim() || undefined,
        mappedAt: Date.now(),
    };
}
export function createChannelArtifactEnvelope(input) {
    const thread = isMappedThread(input.thread)
        ? input.thread
        : mapChannelThread(input.thread);
    return {
        envelopeType: 'nexus.channel.artifact',
        provider: normalizeChannelProvider(input.provider),
        thread,
        artifactType: input.artifactType.trim(),
        artifactId: input.artifactId?.trim() || undefined,
        title: input.title.trim(),
        summary: input.summary.trim(),
        body: input.body?.trim() || undefined,
        attachments: [...(input.attachments ?? [])],
        metadata: { ...(input.metadata ?? {}) },
        createdAt: input.createdAt ?? Date.now(),
    };
}
export class ChannelGateway {
    normalizeProvider(provider) {
        return normalizeChannelProvider(provider);
    }
    mapThread(input) {
        return mapChannelThread(input);
    }
    createArtifactEnvelope(input) {
        return createChannelArtifactEnvelope(input);
    }
    threadKey(input) {
        return buildChannelThreadKey(input);
    }
    conversationKey(input) {
        return buildChannelConversationKey(input);
    }
}
function isMappedThread(value) {
    return typeof value.threadKey === 'string'
        && typeof value.conversationKey === 'string'
        && typeof value.mappedAt === 'number';
}
