"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.send = send;
exports.stringifyJsonWithEscapedQuotes = stringifyJsonWithEscapedQuotes;
exports.stringifyMappingSchemaForGraphQL = stringifyMappingSchemaForGraphQL;
const constants_1 = require("./constants");
const common_constants_1 = require("../common-constants");
const common_functions_1 = require("../common-functions");
async function send(request, payloads, settings) {
    const fieldTypes = getDefaultFieldTypes();
    const fieldsToMap = getDefaultFieldsToMap();
    const advertiserId = settings.advertiser_id;
    const marketingStatus = payloads[0].marketing_status;
    const profileUpdates = payloads.map((p) => {
        const { user_id, standard_traits, custom_traits, email } = p;
        const { segment_computation_key, segment_computation_id, traits_or_props } = p;
        if (custom_traits) {
            delete custom_traits[segment_computation_key];
            delete custom_traits[segment_computation_id];
        }
        const profile = {
            userId: user_id,
            email,
            ...standard_traits,
            ...custom_traits
        };
        profile.audienceId = segment_computation_id;
        profile.audienceName = segment_computation_key;
        profile.action = traits_or_props[segment_computation_key] ? 'enter' : 'exit';
        updateFieldsToMapAndFieldTypes(fieldsToMap, fieldTypes, custom_traits);
        return profile;
    });
    const mappings = getProfileMappings(Array.from(fieldsToMap), fieldTypes);
    const profiles = stringifyJsonWithEscapedQuotes(profileUpdates);
    const mutation = `mutation {
      upsertProfiles(
        input: {
          advertiserId: ${advertiserId},
          externalProvider: "${common_constants_1.EXTERNAL_PROVIDER}",
          syncId: "${(0, common_functions_1.sha256hash)(profiles)}",
          profiles: "${profiles}"
        }
      ) {
        userErrors {
          message
        }
      }
      upsertProfileMapping(
        input: {
          advertiserId: ${advertiserId},
          mappingSchemaV2: ${mappings},
          isOptedIn: ${marketingStatus === constants_1.MarketingStatus.OPT_IN},
          mappableType: "${common_constants_1.EXTERNAL_PROVIDER}"
        }
      ) {
        userErrors {
          message
        }
      }
      ${audienceMutation(advertiserId, stringifyMappingSchemaForGraphQL(constants_1.MAPPING_SCHEMA))}
  }`;
    return await request(common_constants_1.GQL_ENDPOINT, {
        body: JSON.stringify({ query: mutation })
    });
}
function audienceMutation(advertiserId, audienceMapping) {
    return `upsertExternalAudienceMapping(
          input: {
            advertiserId: ${advertiserId},
            mappingSchema: ${audienceMapping},
            mappableType: "${common_constants_1.EXTERNAL_PROVIDER}"
          }
        ) {
          userErrors {
            message
          }
        }`;
}
function updateFieldsToMapAndFieldTypes(fieldsToMap, fieldTypes, customTraits = {}) {
    return Object.keys(customTraits).reduce((acc, key) => {
        const value = customTraits[key];
        if (key === '' || value === '') {
            return acc;
        }
        acc[key] = value;
        const standardFields = getDefaultFieldsToMap();
        if (!standardFields.has(key)) {
            fieldsToMap.add(key);
            if (value || value === 0) {
                const type = getType(value);
                if (fieldTypes[key] && fieldTypes[key] !== type) {
                    fieldTypes[key] = 'STRING';
                }
                else {
                    fieldTypes[key] = type;
                }
            }
        }
        return acc;
    }, {});
}
function getProfileMappings(customFields, fieldTypes) {
    const mappingSchema = [];
    for (const field of customFields) {
        const fieldConfig = constants_1.PROFILE_DEFAULT_FIELDS.find((f) => f.key === field);
        if (fieldConfig) {
            let destinationKey;
            switch (fieldConfig.key) {
                case 'user_id':
                    destinationKey = 'external_id';
                    break;
                default:
                    destinationKey = fieldConfig.key;
            }
            mappingSchema.push({
                incomingKey: field,
                destinationKey,
                label: fieldConfig.label,
                type: fieldConfig.type.toUpperCase(),
                isPii: fieldConfig.isPii || false
            });
        }
        else {
            mappingSchema.push({
                incomingKey: field,
                destinationKey: field,
                label: generateLabel(field),
                type: fieldTypes[field] ?? 'STRING',
                isPii: false
            });
        }
    }
    return stringifyMappingSchemaForGraphQL(mappingSchema);
}
function generateLabel(field) {
    let label = field
        .replace(/_/g, ' ')
        .trim()
        .replace(/\b\w/g, (str) => str.toUpperCase());
    if (field.startsWith('audience')) {
        label = `External ${label}`;
    }
    return label;
}
function getType(value) {
    if (isDateStr(value))
        return 'DATE';
    return (typeof value).toUpperCase();
}
function isDateStr(value) {
    if (typeof value !== 'string')
        return false;
    const datePatterns = [
        /^\d{4}-\d{2}-\d{2}/,
        /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/,
        /^\d{1,2}\/\d{1,2}\/\d{4}/,
        /^\d{1,2}-\d{1,2}-\d{4}/
    ];
    const hasDatePattern = datePatterns.some(pattern => pattern.test(value));
    if (!hasDatePattern)
        return false;
    const parsed = Date.parse(value);
    return !isNaN(parsed);
}
function stringifyJsonWithEscapedQuotes(value) {
    const jsonString = JSON.stringify(value);
    return jsonString.replace(/"/g, '\\"');
}
function stringifyMappingSchemaForGraphQL(value) {
    let jsonString = JSON.stringify(value);
    jsonString = jsonString.replace(/"type":"([^"]+)"/g, (_, typeValue) => `type:${typeValue.toUpperCase()}`);
    jsonString = jsonString.replace(/"([a-zA-Z_][a-zA-Z0-9_]*)"\s*:/g, '$1:');
    return jsonString;
}
const getDefaultFieldsToMap = () => {
    return new Set(constants_1.PROFILE_DEFAULT_FIELDS.map(field => field.key));
};
const getDefaultFieldTypes = () => {
    return constants_1.PROFILE_DEFAULT_FIELDS.reduce((acc, field) => {
        acc[field.key] = field.type.toUpperCase();
        return acc;
    }, {});
};
//# sourceMappingURL=functions.js.map