"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hash = exports.TTD_LIST_ACTION_FLOW_FLAG_NAME = exports.TTD_LEGACY_FLOW_FLAG_NAME = void 0;
exports.processPayload = processPayload;
exports.getAllDataSegments = getAllDataSegments;
const actions_core_1 = require("@segment/actions-core");
const crypto_1 = require("crypto");
const actions_core_2 = require("@segment/actions-core");
const awsClient_1 = require("./awsClient");
const API_VERSION = 'v3';
const BASE_URL = `https://api.thetradedesk.com/${API_VERSION}`;
const TTD_MIN_RECORD_COUNT = 1500;
exports.TTD_LEGACY_FLOW_FLAG_NAME = 'actions-the-trade-desk-crm-legacy-flow';
exports.TTD_LIST_ACTION_FLOW_FLAG_NAME = 'ttd-list-action-destination';
const sha256HashedRegex = /^[a-f0-9]{64}$/i;
const base64HashedRegex = /^[A-Za-z0-9+/]*={1,2}$/i;
const validEmailRegex = /^\S+@\S+\.\S+$/i;
async function processPayload(input) {
    let crmID;
    if (!input.payloads[0].external_id) {
        throw new actions_core_1.PayloadValidationError(`No external_id found in payload.`);
    }
    else {
        crmID = input.payloads[0].external_id;
    }
    const [usersFormatted, rowCount] = extractUsers(input.payloads);
    if (input.features && input.features[exports.TTD_LEGACY_FLOW_FLAG_NAME]) {
        if (input.payloads.length < TTD_MIN_RECORD_COUNT) {
            throw new actions_core_1.PayloadValidationError(`received payload count below The Trade Desk's ingestion minimum. Expected: >=${TTD_MIN_RECORD_COUNT} actual: ${input.payloads.length}`);
        }
        const dropEndpoint = await getCRMDataDropEndpoint(input.request, input.settings, input.payloads[0], crmID);
        return uploadCRMDataToDropEndpoint(input.request, dropEndpoint, usersFormatted);
    }
    else {
        return (0, awsClient_1.sendEventToAWS)({
            TDDAuthToken: input.settings.auth_token,
            AdvertiserId: input.settings.advertiser_id,
            CrmDataId: crmID,
            UsersFormatted: usersFormatted,
            RowCount: rowCount,
            DropOptions: {
                PiiType: input.payloads[0].pii_type,
                MergeMode: 'Replace',
                RetentionEnabled: true
            }
        });
    }
}
function extractUsers(payloads) {
    let users = '';
    let rowCount = 0;
    payloads.forEach((payload) => {
        if (!payload.email || !validateEmail(payload.email, payload.pii_type)) {
            return;
        }
        if (payload.pii_type == 'Email') {
            users += `${payload.email}\n`;
        }
        if (payload.pii_type == 'EmailHashedUnifiedId2') {
            const hashedEmail = (0, exports.hash)(payload.email);
            users += `${hashedEmail}\n`;
        }
        rowCount += 1;
    });
    return [users, rowCount];
}
function validateEmail(email, pii_type) {
    const isSha256HashedEmail = sha256HashedRegex.test(email);
    const isBase64Hashed = base64HashedRegex.test(email);
    const isValidEmail = validEmailRegex.test(email);
    if (pii_type == 'Email') {
        return isValidEmail;
    }
    return isSha256HashedEmail || isBase64Hashed || isValidEmail;
}
function normalizeEmail(email) {
    email = email.trim().toLowerCase();
    if (email.endsWith('@gmail.com')) {
        const findat = email.indexOf('@');
        let username = email.substring(0, findat);
        const findplus = username.indexOf('+');
        if (findplus !== -1) {
            username = username.substring(0, findplus);
        }
        username = username.replace(/\./g, '');
        email = username + '@gmail.com';
    }
    return email;
}
const hash = (value) => {
    const isSha256HashedEmail = sha256HashedRegex.test(value);
    const isBase64Hashed = base64HashedRegex.test(value);
    if (isSha256HashedEmail) {
        return Buffer.from(value, 'hex').toString('base64');
    }
    if (isBase64Hashed) {
        return value;
    }
    const normalizedEmail = normalizeEmail(value);
    const hash = (0, crypto_1.createHash)('sha256');
    hash.update(normalizedEmail);
    return hash.digest('base64');
};
exports.hash = hash;
async function getCRMDataDropEndpoint(request, settings, payload, crmId) {
    const response = await request(`${BASE_URL}/crmdata/segment/${settings.advertiser_id}/${crmId}`, {
        method: 'POST',
        json: {
            PiiType: payload.pii_type,
            MergeMode: 'Replace',
            RetentionEnabled: true
        }
    });
    return response.data.Url;
}
async function uploadCRMDataToDropEndpoint(request, endpoint, users) {
    return await request(endpoint, {
        method: 'PUT',
        headers: {
            'Content-Type': 'text/plain'
        },
        body: users
    });
}
async function getAllDataSegments(request, advertiserId, authToken) {
    const allDataSegments = [];
    let response = await request(`${BASE_URL}/crmdata/segment/${advertiserId}`, {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
            'TTD-Auth': authToken
        }
    });
    if (response.status != 200 || !response.data.Segments) {
        throw new actions_core_2.IntegrationError('Invalid response from get audience request', 'INVALID_RESPONSE', 400);
    }
    let segments = response.data.Segments;
    let pagingToken = response.data.PagingToken;
    while (segments.length > 0) {
        allDataSegments.push(...segments);
        response = await request(`${BASE_URL}/crmdata/segment/${advertiserId}?pagingToken=${pagingToken}`, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'TTD-Auth': authToken
            }
        });
        segments = response.data.Segments;
        pagingToken = response.data.PagingToken;
    }
    return allDataSegments;
}
//# sourceMappingURL=functions.js.map