"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const send_1 = __importDefault(require("../webhook/send"));
const actions_core_1 = require("@segment/actions-core");
const crypto_1 = require("crypto");
const externalIdKey = 'externalId';
const audienceNameKey = 'audienceName';
const destination = {
    name: 'Webhook Audiences',
    slug: 'actions-webhook-audiences',
    mode: 'cloud',
    authentication: {
        scheme: 'custom',
        fields: {
            sharedSecret: {
                type: 'password',
                label: 'Shared Secret',
                description: 'If set, Segment will sign requests with an HMAC in the "X-Signature" request header. The HMAC is a hex-encoded SHA1 hash generated using this shared secret and the request body.'
            },
            createAudienceUrl: {
                type: 'string',
                label: 'URL to send requests to create an audience',
                description: `If set, Segment will send a POST request with the ${audienceNameKey} in the JSON to the provided URL to create the audience. The expected JSON response must have "${externalIdKey}".`
            },
            getAudienceUrl: {
                type: 'string',
                label: 'URL to send requests to get an audience',
                description: `If set, Segment will send a POST request with the ${externalIdKey} in the JSON to the provided URL to get the audience. The expected JSON response must have "${externalIdKey}".`
            }
        }
    },
    audienceFields: {
        extras: {
            type: 'string',
            label: `Extra JSON fields to pass on to every request (as a JSON string)`,
            description: `Extra JSON fields to pass on to every request. This must be a valid JSON string (e.g., "{\\"hello\\": \\"world\\", \\"foo\\": \\"bar\\"}"). The JSON will be parsed and merged into each request payload. Note: "${externalIdKey}" and "${audienceNameKey}" are reserved keys and cannot be used.`
        }
    },
    audienceConfig: {
        mode: {
            type: 'synced',
            full_audience_sync: false
        },
        async getAudience(request, getAudienceInput) {
            const getAudienceUrl = getAudienceInput.settings.getAudienceUrl;
            if (!getAudienceUrl) {
                throw new actions_core_1.IntegrationError('Missing get audience url value', 'MISSING_REQUIRED_FIELD', 400);
            }
            const extras = parseExtraSettingsJson(getAudienceInput.audienceSettings?.extras);
            const response = await request(getAudienceUrl, {
                method: 'POST',
                json: {
                    ...extras,
                    [externalIdKey]: getAudienceInput.externalId
                }
            });
            let jsonOutput;
            try {
                jsonOutput = await response.json();
                if (!jsonOutput[externalIdKey]) {
                    throw new actions_core_1.IntegrationError(`Missing ${externalIdKey} in response (status: ${response.status})`, 'INVALID_RESPONSE', 400);
                }
            }
            catch (error) {
                const errorMessage = error instanceof Error ? error.message : 'Unknown error';
                throw new actions_core_1.IntegrationError(`Invalid response from get audience request (status: ${response.status}): ${errorMessage}`, 'INVALID_RESPONSE', 400);
            }
            return {
                externalId: jsonOutput[externalIdKey]
            };
        },
        async createAudience(request, createAudienceInput) {
            const audienceName = createAudienceInput.audienceName;
            if (audienceName?.length == 0) {
                throw new actions_core_1.IntegrationError('Missing audience name value', 'MISSING_REQUIRED_FIELD', 400);
            }
            const createAudienceUrl = createAudienceInput.settings.createAudienceUrl;
            if (!createAudienceUrl) {
                throw new actions_core_1.IntegrationError('Missing create audience url value', 'MISSING_REQUIRED_FIELD', 400);
            }
            const extras = parseExtraSettingsJson(createAudienceInput.audienceSettings?.extras);
            const response = await request(createAudienceUrl, {
                method: 'POST',
                json: {
                    ...extras,
                    audienceName
                }
            });
            let jsonOutput;
            try {
                jsonOutput = await response.json();
                if (!jsonOutput[externalIdKey]) {
                    throw new actions_core_1.IntegrationError(`Missing ${externalIdKey} in response (status: ${response.status})`, 'INVALID_RESPONSE', 400);
                }
            }
            catch (error) {
                const errorMessage = error instanceof Error ? error.message : 'Unknown error';
                throw new actions_core_1.IntegrationError(`Invalid response from create audience request (status: ${response.status}): ${errorMessage}`, 'INVALID_RESPONSE', 400);
            }
            return {
                externalId: jsonOutput[externalIdKey]
            };
        }
    },
    extendRequest: ({ settings, payload }) => {
        if (!payload) {
            return {};
        }
        const payloadData = payload.length ? payload[0]['data'] : payload['data'];
        if (settings.sharedSecret && payloadData) {
            const digest = (0, crypto_1.createHmac)('sha1', settings.sharedSecret).update(JSON.stringify(payloadData), 'utf8').digest('hex');
            return { headers: { 'X-Signature': digest } };
        }
        return {};
    },
    actions: {
        send: {
            ...send_1.default,
            perform: (request, { payload, settings, audienceSettings }) => {
                const extras = parseExtraSettingsJson(audienceSettings?.extras);
                return send_1.default.perform(request, {
                    audienceSettings,
                    payload: {
                        ...payload,
                        data: {
                            ...payload.data,
                            ...extras
                        }
                    },
                    settings
                });
            },
            performBatch: (request, { payload, settings, audienceSettings, statsContext }) => {
                const extras = parseExtraSettingsJson(audienceSettings?.extras);
                if (statsContext) {
                    const { statsClient, tags } = statsContext;
                    const set = new Set();
                    for (const p of payload) {
                        set.add(`${p.url} ${p.method} ${JSON.stringify(p.headers)}`);
                    }
                    statsClient?.histogram('webhook.configurable_batch_keys.unique_keys', set.size, tags);
                }
                return send_1.default.performBatch(request, {
                    audienceSettings,
                    payload: payload.map((p) => {
                        return {
                            ...p,
                            data: {
                                ...p.data,
                                ...extras
                            }
                        };
                    }),
                    settings
                });
            }
        }
    },
    presets: [
        {
            name: 'Entities Audience Membership Changed',
            partnerAction: 'send',
            mapping: (0, actions_core_1.defaultValues)(send_1.default.fields),
            type: 'specificEvent',
            eventSlug: 'warehouse_audience_membership_changed_identify'
        },
        {
            name: 'Associated Entity Added',
            partnerAction: 'send',
            mapping: (0, actions_core_1.defaultValues)(send_1.default.fields),
            type: 'specificEvent',
            eventSlug: 'warehouse_entity_added_track'
        },
        {
            name: 'Associated Entity Removed',
            partnerAction: 'send',
            mapping: (0, actions_core_1.defaultValues)(send_1.default.fields),
            type: 'specificEvent',
            eventSlug: 'warehouse_entity_removed_track'
        },
        {
            name: 'Journeys Step Entered',
            partnerAction: 'send',
            mapping: (0, actions_core_1.defaultValues)(send_1.default.fields),
            type: 'specificEvent',
            eventSlug: 'journeys_step_entered_track'
        }
    ]
};
const parseExtraSettingsJson = (extraSettingsJson) => {
    let extraSettings = {};
    if (extraSettingsJson) {
        try {
            extraSettings = JSON.parse(extraSettingsJson);
        }
        catch (e) {
            throw new actions_core_1.IntegrationError('Invalid extraSettings JSON', 'INVALID_REQUEST_DATA', 400);
        }
    }
    return extraSettings;
};
exports.default = destination;
//# sourceMappingURL=index.js.map