"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.send = send;
exports.sendRequest = sendRequest;
exports.setErrorResponse = setErrorResponse;
exports.returnErrorResponse = returnErrorResponse;
exports.getAudienceId = getAudienceId;
exports.getJSON = getJSON;
exports.validate = validate;
exports.getData = getData;
exports.normalizePhone = normalizePhone;
exports.normalizeGender = normalizeGender;
exports.normalizeMonth = normalizeMonth;
exports.normalizeName = normalizeName;
exports.normalizeCity = normalizeCity;
exports.normalizeState = normalizeState;
exports.normalizeZip = normalizeZip;
exports.normalizeCountry = normalizeCountry;
const constants_1 = require("./constants");
const actions_core_1 = require("@segment/actions-core");
const hashing_utils_1 = require("../../../lib/hashing-utils");
const constants_2 = require("../constants");
const functions_1 = require("../functions");
async function send(request, payloads, isBatch, audienceMemberships, hookOutputs, features, statsContext) {
    const msResponse = new actions_core_1.MultiStatusResponse();
    const audienceId = getAudienceId(payloads[0], hookOutputs);
    const errorMessage = validate(payloads, audienceId, audienceMemberships);
    if (errorMessage) {
        return returnErrorResponse(msResponse, payloads, isBatch, errorMessage, actions_core_1.ErrorCodes.PAYLOAD_VALIDATION_FAILED);
    }
    const addMap = new Map();
    const deleteMap = new Map();
    payloads.forEach((payload, index) => {
        const audienceMembership = audienceMemberships?.[index];
        if (audienceMembership === false) {
            deleteMap.set(index, payload);
        }
        else if (audienceMembership === true) {
            addMap.set(index, payload);
        }
        else if (audienceMembership === undefined) {
            setErrorResponse(msResponse, payload, 400, index, isBatch, "Audience membership details missing", actions_core_1.ErrorCodes.PAYLOAD_VALIDATION_FAILED);
        }
    });
    const requests = [];
    if (addMap.size > 0) {
        requests.push(sendRequest(request, audienceId, addMap, msResponse, 'POST', isBatch, features, statsContext));
    }
    if (deleteMap.size > 0) {
        requests.push(sendRequest(request, audienceId, deleteMap, msResponse, 'DELETE', isBatch, features, statsContext));
    }
    await Promise.all(requests);
    if (isBatch) {
        return msResponse;
    }
}
async function sendRequest(request, audienceId, map, msResponse, method, isBatch, features, statsContext) {
    const indices = Array.from(map.keys());
    const payloads = Array.from(map.values());
    const json = getJSON(payloads);
    try {
        await request(`${constants_2.BASE_URL}/${(0, functions_1.getApiVersion)(features, statsContext)}/${audienceId}/users`, {
            method,
            json
        });
        for (let i = 0; i < indices.length; i++) {
            const originalIndex = indices[i];
            msResponse.setSuccessResponseAtIndex(originalIndex, {
                status: 200,
                body: payloads[i],
                sent: {
                    data: json.payload.data[i],
                    method,
                    audienceId
                }
            });
        }
    }
    catch (error) {
        const { message, code, status } = (0, functions_1.parseFacebookError)(error);
        for (let i = 0; i < indices.length; i++) {
            const sent = {
                data: json.payload.data[i],
                method,
                audienceId
            };
            setErrorResponse(msResponse, payloads[i], status, indices[i], isBatch, message, code, sent);
        }
    }
}
function setErrorResponse(msResponse, payload, status, index, isBatch, errormessage, errortype, sent) {
    if (!isBatch) {
        if (errortype === actions_core_1.ErrorCodes.PAYLOAD_VALIDATION_FAILED) {
            throw new actions_core_1.PayloadValidationError(errormessage);
        }
        throw new actions_core_1.IntegrationError(errormessage, errortype, status);
    }
    msResponse.setErrorResponseAtIndex(index, {
        status,
        errortype: errortype,
        errormessage,
        body: payload,
        ...(sent ? { sent } : {})
    });
}
function returnErrorResponse(msResponse, payloads, isBatch, errormessage, errortype) {
    payloads.forEach((payload, i) => {
        setErrorResponse(msResponse, payload, 400, i, isBatch, errormessage, errortype);
    });
    return msResponse;
}
function getAudienceId(payload, hookOutputs) {
    const { retlOnMappingSave: { outputs: { audienceId: hookAudienceId = undefined } = {} } = {} } = hookOutputs ?? {};
    const { external_audience_id: payloadAudienceId } = payload;
    return (hookAudienceId ?? payloadAudienceId);
}
function getJSON(payloads) {
    const data = getData(payloads);
    const app_ids = [];
    const page_ids = [];
    const ig_account_ids = [];
    payloads.forEach((payload) => {
        const { appId, pageId, igAccountIds } = payload;
        app_ids.push(typeof appId === 'string' && appId ? appId : '');
        page_ids.push(typeof pageId === 'string' && pageId ? pageId : '');
        ig_account_ids.push(typeof igAccountIds === 'string' && igAccountIds ? igAccountIds : '');
    });
    return {
        payload: {
            schema: constants_1.SCHEMA_PROPERTIES,
            data,
            ...(app_ids?.some((id) => id?.trim() !== '') ? { app_ids } : {}),
            ...(page_ids?.some((id) => id?.trim() !== '') ? { page_ids } : {}),
            ...(ig_account_ids?.some((id) => id?.trim() !== '') ? { ig_account_ids } : {})
        }
    };
}
function validate(payloads, audienceId, audienceMemberships) {
    if (!Array.isArray(audienceMemberships)) {
        return 'Audience membership details for batch missing.';
    }
    if (Array.isArray(audienceMemberships) && audienceMemberships.length !== payloads.length) {
        return 'Audience membership details count does not match batch payload count.';
    }
    if (!audienceId || typeof audienceId !== 'string') {
        return 'Missing audience ID.';
    }
}
function getData(payloads) {
    const data = new Array(payloads.length);
    payloads.forEach((payload, index) => {
        const { externalId, email, phone, birth: { year, month, day } = {}, name: { last, first, firstInitial } = {}, gender, city, state, zip, country, mobileAdId } = payload;
        const row = [
            externalId ?? '',
            email ? (0, hashing_utils_1.processHashing)(email.trim().toLowerCase(), 'sha256', 'hex') : '',
            phone ? (0, hashing_utils_1.processHashing)(phone, 'sha256', 'hex', normalizePhone) ?? '' : '',
            year ? (0, hashing_utils_1.processHashing)(year.trim(), 'sha256', 'hex') ?? '' : '',
            month ? (0, hashing_utils_1.processHashing)(normalizeMonth(month), 'sha256', 'hex') ?? '' : '',
            day ? (0, hashing_utils_1.processHashing)(day.trim(), 'sha256', 'hex') ?? '' : '',
            last ? (0, hashing_utils_1.processHashing)(normalizeName(last), 'sha256', 'hex') ?? '' : '',
            first ? (0, hashing_utils_1.processHashing)(normalizeName(first), 'sha256', 'hex') ?? '' : '',
            firstInitial ? (0, hashing_utils_1.processHashing)(firstInitial.trim().toLowerCase(), 'sha256', 'hex') ?? '' : '',
            gender ? (0, hashing_utils_1.processHashing)(normalizeGender(gender), 'sha256', 'hex') ?? '' : '',
            city ? (0, hashing_utils_1.processHashing)(normalizeCity(city), 'sha256', 'hex') ?? '' : '',
            state ? (0, hashing_utils_1.processHashing)(normalizeState(state), 'sha256', 'hex') ?? '' : '',
            zip ? (0, hashing_utils_1.processHashing)(normalizeZip(zip), 'sha256', 'hex') ?? '' : '',
            country ? (0, hashing_utils_1.processHashing)(normalizeCountry(country), 'sha256', 'hex') ?? '' : '',
            mobileAdId ?? ''
        ];
        data[index] = row;
    });
    return data;
}
function normalizePhone(value) {
    const removedNonNumveric = value.replace(/\D/g, '');
    return removedNonNumveric.replace(/^0+/, '');
}
function normalizeGender(value) {
    const lowerCaseValue = value.toLowerCase().trim();
    if (['male', 'boy', 'm'].includes(lowerCaseValue))
        return 'm';
    if (['female', 'woman', 'girl', 'f'].includes(lowerCaseValue))
        return 'f';
    return value;
}
function normalizeMonth(value) {
    const normalizedValue = value.replace(/\s/g, '').trim();
    if (normalizedValue.length === 2 && typeof Number(normalizedValue) === 'number') {
        return normalizedValue;
    }
    const lowerCaseValue = value.trim().toLowerCase();
    const months = [
        'january',
        'february',
        'march',
        'april',
        'may',
        'june',
        'july',
        'august',
        'september',
        'october',
        'november',
        'december'
    ];
    const monthIndex = months.indexOf(lowerCaseValue);
    if (monthIndex === -1) {
        return value;
    }
    if (monthIndex < 9) {
        return `0${monthIndex + 1}`;
    }
    return `${monthIndex + 1}`;
}
function normalizeName(value) {
    return value.trim().toLowerCase().replace(/\p{P}/gu, '');
}
function normalizeCity(value) {
    return value
        .trim()
        .replace(/[\s\W_]/g, '')
        .toLowerCase();
}
function normalizeState(value) {
    if (constants_1.US_STATE_CODES.has(value.toLowerCase().trim())) {
        return constants_1.US_STATE_CODES.get(value.toLowerCase().trim());
    }
    return value
        .trim()
        .replace(/[\s\W_]/g, '')
        .toLowerCase();
}
function normalizeZip(value) {
    if (value.includes('-')) {
        return value.split('-')[0];
    }
    return value.trim().replace(/\s/g, '').toLowerCase();
}
function normalizeCountry(value) {
    return value
        .trim()
        .replace(/[\s\W_]/g, '')
        .toLowerCase();
}
//# sourceMappingURL=functions.js.map