"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.processPayload = processPayload;
exports.createPayloadToUploadRecords = createPayloadToUploadRecords;
exports.processBatchPayload = processBatchPayload;
exports.updateMultiStatusResponses = updateMultiStatusResponses;
const actions_core_1 = require("@segment/actions-core");
const actions_core_2 = require("@segment/actions-core");
const utils_1 = require("./utils");
const hashing_utils_1 = require("../../lib/hashing-utils");
const versioning_info_1 = require("./versioning-info");
function hasStringValue(value) {
    return typeof value === 'string' && value.trim().length > 0;
}
function getUserConsent(payloadConsent, countryCode, features) {
    const { ipAddress, amznAdStorage, amznUserData, tcf, gpp } = payloadConsent || {};
    const enableErrors = features?.[utils_1.FLAG_CONSENT_ENABLE_ERRORS];
    if (!utils_1.COUNTRY_CODES.includes(countryCode)) {
        if (enableErrors) {
            throw new actions_core_2.PayloadValidationError(`Invalid country code: ${countryCode}. Country code must be a valid ISO 3166-1 alpha-2 code.`);
        }
    }
    const amzn = hasStringValue(amznAdStorage) && hasStringValue(amznUserData) ? { amznAdStorage: amznAdStorage === 'GRANTED' ? 'GRANTED' : 'DENIED', amznUserData: amznUserData === 'GRANTED' ? 'GRANTED' : 'DENIED' } : undefined;
    if (utils_1.UK_EEA_COUNTRY_CODES.includes(countryCode) && !amzn && !hasStringValue(tcf) && !hasStringValue(gpp)) {
        if (enableErrors) {
            throw new actions_core_2.PayloadValidationError(`Consent required when sending data with UK and EEA country code ${countryCode}. Please provide valid consent for amznAdStorage and amznUserData or TCF or GPP.`);
        }
    }
    const geo = {
        ...(hasStringValue(ipAddress) && { ipAddress }),
        countryCode
    };
    const consent = {
        ...(amzn && { amzn }),
        ...(hasStringValue(tcf) && { tcf }),
        ...(hasStringValue(gpp) && { gpp })
    };
    const consentData = {
        geo,
        ...(Object.keys(consent).length > 0 && { consent })
    };
    return consentData;
}
async function processPayload(request, settings, payload, audienceSettings, features) {
    const payloadRecord = createPayloadToUploadRecords(payload, audienceSettings, features);
    const payloadString = JSON.stringify(payloadRecord).replace(/"audienceId":"(\d+)"/, '"audienceId":$1');
    const response = await request(`${settings.region}/amc/audiences/records`, {
        method: 'POST',
        body: payloadString,
        headers: {
            'Content-Type': `application/vnd.amcaudiences.${versioning_info_1.AMAZON_AMC_API_VERSION}+json`
        },
        timeout: 15000
    });
    const result = response.data;
    return {
        result
    };
}
function createPayloadToUploadRecords(payloads, audienceSettings, features) {
    const records = [];
    const { audienceId } = payloads[0];
    payloads.forEach((payload) => {
        if (!utils_1.REGEX_EXTERNALUSERID.test(payload.externalUserId)) {
            return;
        }
        const userConsent = features?.[utils_1.FLAG_CONSENT_REQUIRED] ? getUserConsent(payload.consent, audienceSettings.countryCode, features) : undefined;
        const hashedPII = hashedPayload(payload);
        const payloadRecord = {
            externalUserId: payload.externalUserId,
            countryCode: audienceSettings.countryCode,
            action: payload.event_name == 'Audience Entered' ? utils_1.CONSTANTS.CREATE : utils_1.CONSTANTS.DELETE,
            hashedPII: [hashedPII],
            ...(userConsent ? { userConsent } : {})
        };
        records.push(payloadRecord);
    });
    if (!records?.length) {
        throw new actions_core_2.PayloadValidationError('externalUserId must satisfy regular expression pattern: [0-9a-zA-Z\\-\\_]{1,128}}');
    }
    return {
        records: records,
        audienceId: audienceId
    };
}
function validateAndPreparePayload(payloads, multiStatusResponse, audienceSettings, features) {
    const validPayloadIndicesBitmap = [];
    const filteredPayloads = [];
    payloads.forEach((payload, originalBatchIndex) => {
        if (!utils_1.REGEX_EXTERNALUSERID.test(payload.externalUserId)) {
            multiStatusResponse.setErrorResponseAtIndex(originalBatchIndex, {
                status: 400,
                errortype: 'PAYLOAD_VALIDATION_FAILED',
                errormessage: 'externalUserId must satisfy regular expression pattern: [0-9a-zA-Z\\-\\_]{1,128}}'
            });
            return;
        }
        let userConsent;
        try {
            userConsent = features?.[utils_1.FLAG_CONSENT_REQUIRED] ? getUserConsent(payload.consent, audienceSettings.countryCode, features) : undefined;
        }
        catch (error) {
            multiStatusResponse.setErrorResponseAtIndex(originalBatchIndex, {
                status: error.status || 400,
                errortype: 'PAYLOAD_VALIDATION_FAILED',
                errormessage: error.message,
                body: payload
            });
            return;
        }
        const hashedPII = hashedPayload(payload);
        const payloadRecord = {
            externalUserId: payload.externalUserId,
            countryCode: audienceSettings.countryCode,
            action: payload.event_name == 'Audience Entered' ? utils_1.CONSTANTS.CREATE : utils_1.CONSTANTS.DELETE,
            hashedPII: [hashedPII],
            ...(userConsent ? { userConsent } : {})
        };
        filteredPayloads.push(payloadRecord);
        validPayloadIndicesBitmap.push(originalBatchIndex);
    });
    return { filteredPayloads, validPayloadIndicesBitmap };
}
async function processBatchPayload(request, settings, payloads, audienceSettings, features) {
    const multiStatusResponse = new actions_core_2.MultiStatusResponse();
    const { filteredPayloads, validPayloadIndicesBitmap } = validateAndPreparePayload(payloads, multiStatusResponse, audienceSettings, features);
    if (!filteredPayloads.length) {
        return multiStatusResponse;
    }
    const payloadString = JSON.stringify({ audienceId: payloads[0].audienceId, records: filteredPayloads }).replace(/"audienceId":"(\d+)"/, '"audienceId":$1');
    const response = await request(`${settings.region}/amc/audiences/records`, {
        method: 'POST',
        body: payloadString,
        throwHttpErrors: false,
        headers: {
            'Content-Type': 'application/vnd.amcaudiences.v1+json'
        },
        timeout: 15000
    });
    if (!response.ok && response.status == 401) {
        throw new actions_core_1.InvalidAuthenticationError(response.statusText);
    }
    return updateMultiStatusResponses(filteredPayloads, validPayloadIndicesBitmap, multiStatusResponse, response);
}
function updateMultiStatusResponses(filteredPayloads, validPayloadIndicesBitmap, multiStatusResponse, response) {
    filteredPayloads.forEach((payload, index) => {
        const indexBitmap = validPayloadIndicesBitmap[index];
        if (response.ok) {
            multiStatusResponse.setSuccessResponseAtIndex(indexBitmap, {
                status: response.status || 200,
                sent: payload,
                body: response?.data || 'success'
            });
        }
        else {
            multiStatusResponse.setErrorResponseAtIndex(indexBitmap, {
                status: response?.status || 400,
                errormessage: response?.statusText,
                sent: payload,
                body: response?.data
            });
        }
    });
    return multiStatusResponse;
}
function normalize(value, allowedChars, trim = true) {
    let normalized = value.toLowerCase().replace(allowedChars, '');
    if (trim)
        normalized = normalized.trim();
    return normalized;
}
const alphanumeric = /[^a-z0-9]/g;
const emailAllowed = /[^a-z0-9.@-]/g;
const nonDigits = /[^\d]/g;
function normalizeStandard(value) {
    return normalize(value, alphanumeric);
}
function normalizePhone(phone) {
    return normalize(phone, nonDigits);
}
function normalizeEmail(email) {
    return normalize(email, emailAllowed);
}
function hashedPayload(payload) {
    const hashedPII = {};
    if (payload.firstName) {
        hashedPII.firstname = (0, hashing_utils_1.processHashing)(payload.firstName, 'sha256', 'hex', normalizeStandard);
    }
    if (payload.lastName) {
        hashedPII.lastname = (0, hashing_utils_1.processHashing)(payload.lastName, 'sha256', 'hex', normalizeStandard);
    }
    if (payload.address) {
        hashedPII.address = (0, hashing_utils_1.processHashing)(payload.address, 'sha256', 'hex', normalizeStandard);
    }
    if (payload.postal) {
        hashedPII.postal = (0, hashing_utils_1.processHashing)(payload.postal, 'sha256', 'hex', normalizeStandard);
    }
    if (payload.phone) {
        hashedPII.phone = (0, hashing_utils_1.processHashing)(payload.phone, 'sha256', 'hex', normalizePhone);
    }
    if (payload.city) {
        hashedPII.city = (0, hashing_utils_1.processHashing)(payload.city, 'sha256', 'hex', normalizeStandard);
    }
    if (payload.state) {
        hashedPII.state = (0, hashing_utils_1.processHashing)(payload.state, 'sha256', 'hex', normalizeStandard);
    }
    if (payload.email) {
        hashedPII.email = (0, hashing_utils_1.processHashing)(payload.email, 'sha256', 'hex', normalizeEmail);
    }
    return hashedPII;
}
//# sourceMappingURL=function.js.map