"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hasStringValue = hasStringValue;
exports.validateConsent = validateConsent;
exports.normalize = normalize;
exports.normalizeEmail = normalizeEmail;
exports.normalizePhone = normalizePhone;
exports.normalizeStandard = normalizeStandard;
exports.normalizePostal = normalizePostal;
exports.smartHash = smartHash;
exports.sendEventsRequest = sendEventsRequest;
exports.validateCountryCode = validateCountryCode;
exports.handleResponse = handleResponse;
exports.handleBatchResponse = handleBatchResponse;
exports.prepareEventData = prepareEventData;
const actions_core_1 = require("@segment/actions-core");
const hashing_utils_1 = require("../../../lib/hashing-utils");
const types_1 = require("../types");
function hasStringValue(value) {
    return typeof value === 'string' && value.trim().length > 0;
}
function validateConsent(consent, region) {
    const { ipAddress, amznAdStorage, amznUserData, tcf, gpp } = consent || {};
    const consentData = {
        ...(hasStringValue(ipAddress) && { geo: { ipAddress } }),
        ...(hasStringValue(amznAdStorage) &&
            hasStringValue(amznUserData) && {
            amazonConsent: {
                amznAdStorage,
                amznUserData
            }
        }),
        ...(hasStringValue(tcf) && { tcf }),
        ...(hasStringValue(gpp) && { gpp })
    };
    const hasAnyConsent = Object.keys(consentData).length > 0;
    if (region === types_1.Region.EU && !hasAnyConsent) {
        throw new actions_core_1.IntegrationError('At least one type of consent (Geographic info, Amazon consent, Transparency and Consent Framework (TCF), Global Privacy Platform (GPP)) is required for the EU region.', 'MISSING_CONSENT', 400);
    }
    return hasAnyConsent ? consentData : undefined;
}
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;
const whitespace = /\s+/g;
function normalizeEmail(email) {
    return normalize(email, emailAllowed);
}
function normalizePhone(phone) {
    return normalize(phone, nonDigits);
}
function normalizeStandard(value) {
    return normalize(value, alphanumeric);
}
function normalizePostal(postal) {
    return normalize(postal, whitespace, false);
}
function smartHash(value, normalizeFunction) {
    return (0, hashing_utils_1.processHashing)(value, 'sha256', 'hex', normalizeFunction);
}
async function sendEventsRequest(request, settings, eventData) {
    const events = Array.isArray(eventData) ? eventData : [eventData];
    return await request(`${settings.region}/events/v1`, {
        method: 'POST',
        json: {
            eventData: events,
            ingestionMethod: 'SERVER_TO_SERVER'
        },
        headers: {
            'Amazon-Ads-AccountId': settings.advertiserId
        },
        timeout: 25000,
        throwHttpErrors: false
    });
}
function validateCountryCode(input) {
    const normalized = input.trim();
    const localeMatch = normalized.match(/^[a-zA-Z]{2,3}-([A-Z]{2})$/);
    if (localeMatch) {
        return localeMatch[1];
    }
    if (/^[A-Z]{2}$/.test(normalized)) {
        return normalized;
    }
    throw new actions_core_1.IntegrationError('Country code must be in ISO 3166-1 alpha-2 format (e.g., US, CA) or a valid locale format (e.g., en-US).', 'MISSING_COUNTRY_CODE', 400);
}
function handleResponse(response) {
    if (response.status === 207 && response.data) {
        const responseData = response.data;
        if (responseData.error && Array.isArray(responseData.error) && responseData.error.length > 0) {
            return {
                ...response,
                status: Number(responseData.error[0].httpStatusCode) || 400
            };
        }
    }
    return response;
}
function handleBatchResponse(response, validPayloads, validPayloadIndicesBitmap, multiStatusResponse) {
    if (response.status === 207 && response.data) {
        const responseData = response.data;
        const successMap = {};
        const errorMap = {};
        if (responseData.success && Array.isArray(responseData.success)) {
            responseData.success.forEach((item) => {
                successMap[item.index - 1] = item;
            });
        }
        if (responseData.error && Array.isArray(responseData.error)) {
            responseData.error.forEach((item) => {
                errorMap[item.index - 1] = item;
            });
        }
        validPayloads.forEach((payload, arrayPosition) => {
            const originalIndex = validPayloadIndicesBitmap[arrayPosition];
            if (errorMap[arrayPosition]) {
                const errorResult = errorMap[arrayPosition];
                multiStatusResponse.setErrorResponseAtIndex(originalIndex, {
                    status: parseInt(errorResult.httpStatusCode || '400', 10),
                    sent: payload,
                    body: errorResult,
                    errormessage: errorResult.subErrors?.[0]?.errorMessage || 'Error processing payload'
                });
            }
            else if (successMap[arrayPosition]) {
                multiStatusResponse.setSuccessResponseAtIndex(originalIndex, {
                    status: 200,
                    sent: payload,
                    body: successMap[arrayPosition]
                });
            }
            else {
                throw new actions_core_1.APIError('Unable to match event in request payload to response from Amazon API', 500);
            }
        });
    }
    else {
        validPayloadIndicesBitmap.forEach((originalIndex, arrayPosition) => {
            multiStatusResponse.setErrorResponseAtIndex(originalIndex, {
                status: response.status || 400,
                errormessage: response.statusText || 'Amazon API request failed',
                sent: validPayloads[arrayPosition]
            });
        });
    }
    return multiStatusResponse;
}
function prepareEventData(payload, settings) {
    const { customAttributes, matchKeys: { email, phone, firstName, lastName, address, city, state, postalCode, maid, rampId, matchId } = {} } = payload;
    let matchKeys = [];
    if (email && typeof email === 'string') {
        const hashedEmail = smartHash(email, normalizeEmail);
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.EMAIL,
            values: [hashedEmail]
        });
    }
    if (phone && typeof phone === 'string') {
        const hashedPhone = smartHash(phone, normalizePhone);
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.PHONE,
            values: [hashedPhone]
        });
    }
    if (firstName && typeof firstName === 'string') {
        const hashedFirstName = smartHash(firstName, normalizeStandard);
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.FIRST_NAME,
            values: [hashedFirstName]
        });
    }
    if (lastName && typeof lastName === 'string') {
        const hashedLastName = smartHash(lastName, normalizeStandard);
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.LAST_NAME,
            values: [hashedLastName]
        });
    }
    if (address && typeof address === 'string') {
        const hashedAddress = smartHash(address, normalizeStandard);
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.ADDRESS,
            values: [hashedAddress]
        });
    }
    if (city && typeof city === 'string') {
        const hashedCity = smartHash(city, normalizeStandard);
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.CITY,
            values: [hashedCity]
        });
    }
    if (state && typeof state === 'string') {
        const hashedState = smartHash(state, normalizeStandard);
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.STATE,
            values: [hashedState]
        });
    }
    if (postalCode && typeof postalCode === 'string') {
        const hashedPostalCode = smartHash(postalCode, normalizePostal);
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.POSTAL,
            values: [hashedPostalCode]
        });
    }
    if (maid && typeof maid === 'string') {
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.MAID,
            values: [maid]
        });
    }
    if (rampId && typeof rampId === 'string') {
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.RAMP_ID,
            values: [rampId]
        });
    }
    if (matchId && typeof matchId === 'string') {
        matchKeys.push({
            type: types_1.MatchKeyTypeV1.MATCH_ID,
            values: [matchId]
        });
    }
    if (matchKeys.length > 11) {
        matchKeys = matchKeys.slice(0, 11);
    }
    if (matchKeys.length === 0) {
        throw new actions_core_1.IntegrationError('At least one valid match key must be provided.', 'MISSING_MATCH_KEY', 400);
    }
    const customAttributeArray = [];
    Object.entries(customAttributes ?? {}).forEach(([key, value]) => {
        if (value === undefined || value === null)
            return;
        customAttributeArray.push({
            name: key,
            value: typeof value === 'object' ? JSON.stringify(value) : String(value)
        });
    });
    const eventData = {
        name: payload.name,
        eventType: payload.eventType,
        eventActionSource: payload.eventActionSource.toUpperCase(),
        countryCode: validateCountryCode(payload.countryCode),
        timestamp: payload.timestamp
    };
    if (matchKeys) {
        eventData.matchKeys = matchKeys;
    }
    const consent = validateConsent(payload.consent, settings.region);
    Object.assign(eventData, {
        ...(payload.value !== undefined && { value: payload.value }),
        ...(payload.eventType === types_1.ConversionTypeV2.OFF_AMAZON_PURCHASES && payload.currencyCode && {
            currencyCode: payload.currencyCode
        }),
        ...(payload.eventType === types_1.ConversionTypeV2.OFF_AMAZON_PURCHASES && payload.unitsSold !== undefined && {
            unitsSold: payload.unitsSold
        }),
        ...(payload.clientDedupeId && { clientDedupeId: payload.clientDedupeId }),
        ...(payload.dataProcessingOptions && { dataProcessingOptions: payload.dataProcessingOptions }),
        ...(consent && { consent }),
        ...(payload.customAttributes && {
            customAttributes: customAttributeArray.length > 0 ? customAttributeArray : undefined
        })
    });
    return eventData;
}
//# sourceMappingURL=utils.js.map