"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const functions_1 = require("../functions");
const actions_core_1 = require("@segment/actions-core");
const functions_2 = require("../functions");
const config_1 = require("../config");
const properties_1 = require("../properties");
const action = {
    title: 'Subscribe Profile',
    description: 'Subscribe Klaviyo profiles to Email marketing, SMS marketing, or both.',
    defaultSubscription: 'type = "track" and event = "User Subscribed"',
    fields: {
        email: {
            label: 'Email',
            description: `The email address to subscribe. If provided, the associated profile will be subscribed to Email marketing.`,
            type: 'string',
            format: 'email',
            default: {
                '@if': {
                    exists: { '@path': '$.traits.email' },
                    then: { '@path': '$.traits.email' },
                    else: { '@path': '$.context.traits.email' }
                }
            }
        },
        phone_number: {
            label: 'Phone Number',
            description: `The phone number to subscribe. This must be in E.164 format. If provided, the associated profile will be subscribed to SMS marketing.`,
            type: 'string',
            default: {
                '@if': {
                    exists: { '@path': '$.traits.phone' },
                    then: { '@path': '$.traits.phone' },
                    else: { '@path': '$.context.traits.phone' }
                }
            }
        },
        country_code: {
            ...properties_1.country_code
        },
        list_id: {
            label: 'List Id',
            description: `The Klaviyo list to add the newly subscribed profiles to. If no List Id is present, the opt-in process used to subscribe the profile depends on the account's default opt-in settings.`,
            type: 'string',
            dynamic: true
        },
        custom_source: {
            label: 'Custom Source ($source)',
            description: 'A custom method or source to detail source of consent preferences (e.g., "Marketing Event"). The default is set to -59, as this is [the $source value associated with Segment](https://help.klaviyo.com/hc/en-us/articles/1260804673530#h_01HDKHG9AM4BSSM009BM6XBF1H).',
            type: 'string',
            default: '-59'
        },
        historical_import: {
            label: 'Historical Import',
            description: `When set to true, the profile will be subscribed as a historical import. This is useful for importing existing profiles into Klaviyo without sending them an email or SMS.`,
            type: 'boolean',
            default: false
        },
        consented_at: {
            label: 'Consented At',
            description: `The timestamp of when the profile's consent was gathered.`,
            type: 'datetime',
            default: {
                '@path': '$.timestamp'
            }
        },
        enable_batching: {
            type: 'boolean',
            label: 'Batch Data to Klaviyo',
            description: 'When enabled, the action will use the Klaviyo batch API.'
        },
        batch_keys: {
            label: 'Batch Keys',
            description: 'The keys to use for batching the events.',
            type: 'string',
            unsafe_hidden: true,
            required: false,
            multiple: true,
            default: ['list_id', 'custom_source', 'historical_import']
        }
    },
    dynamicFields: {
        list_id: async (request) => {
            return (0, functions_1.getListIdDynamicData)(request);
        }
    },
    perform: async (request, { payload }) => {
        const { email, phone_number: initialPhoneNumber, consented_at, list_id, custom_source, country_code, historical_import } = payload;
        const phone_number = (0, functions_1.processPhoneNumber)(initialPhoneNumber, country_code);
        if (!email && !phone_number) {
            throw new actions_core_1.PayloadValidationError('Phone Number or Email is required.');
        }
        const profileToSubscribe = (0, functions_2.formatSubscribeProfile)(email, phone_number, consented_at, historical_import);
        const subData = (0, functions_2.formatSubscribeRequestBody)(profileToSubscribe, list_id, custom_source, historical_import);
        return await request(`${config_1.API_URL}/profile-subscription-bulk-create-jobs/`, {
            method: 'POST',
            json: subData
        });
    },
    performBatch: async (request, { payload, statsContext }) => {
        const filteredPayload = payload.filter((profile) => {
            const validPhoneNumber = (0, functions_1.validateAndConvertPhoneNumber)(profile.phone_number, profile.country_code);
            if (validPhoneNumber) {
                profile.phone_number = validPhoneNumber;
            }
            else if (validPhoneNumber === null) {
                return false;
            }
            return profile.email || profile.phone_number;
        });
        if (statsContext) {
            const { statsClient, tags } = statsContext;
            const set = new Set();
            filteredPayload.forEach((profile) => {
                set.add(`${profile.list_id}-${profile.custom_source}`);
            });
            statsClient?.histogram('actions-klaviyo.subscribe_profile.unique_list_id', set.size, tags);
        }
        if (filteredPayload.length === 0) {
            throw new actions_core_1.PayloadValidationError('Phone Number or Email is required.');
        }
        const sortedProfilesObject = sortBatches(filteredPayload);
        const batches = Object.keys(sortedProfilesObject);
        if (batches.length > 9) {
            throw new actions_core_1.PayloadValidationError('Exceeded maximum allowed batches due to unique list_id and custom_source pairings');
        }
        const requests = [];
        batches.forEach((key) => {
            const { list_id, custom_source, profiles } = sortedProfilesObject[key];
            for (let i = 0; i < profiles.length; i += 100) {
                const profilesSubset = profiles.slice(i, i + 100);
                const subData = (0, functions_2.formatSubscribeRequestBody)(profilesSubset, list_id, custom_source, payload[0]?.historical_import);
                const response = request(`${config_1.API_URL}/profile-subscription-bulk-create-jobs/`, {
                    method: 'POST',
                    json: subData
                });
                requests.push(response);
            }
        });
        return await Promise.all(requests);
    }
};
exports.default = action;
function sortBatches(batchPayload) {
    const output = {};
    batchPayload.forEach((payload) => {
        const { email, phone_number, custom_source, consented_at, list_id, historical_import } = payload;
        const listId = list_id || 'noListId';
        const customSource = custom_source || 'noCustomSource';
        const key = `${listId}${customSource}`;
        if (!output[key]) {
            const batch = {
                profiles: []
            };
            if (list_id !== undefined) {
                batch.list_id = list_id;
            }
            if (custom_source !== undefined) {
                batch.custom_source = custom_source;
            }
            output[key] = batch;
        }
        const profileToSubscribe = (0, functions_2.formatSubscribeProfile)(email, phone_number, consented_at, historical_import);
        output[key].profiles.push(profileToSubscribe);
    });
    return output;
}
//# sourceMappingURL=index.js.map