"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.objectSchema = objectSchema;
exports.formatHS = formatHS;
exports.compareSchemas = compareSchemas;
const actions_core_1 = require("@segment/actions-core");
const types_1 = require("../types");
function objectSchema(payloads, objectType) {
    const extractProperties = (propertyType) => {
        return Object.values(payloads.reduce((acc, payload) => {
            const properties = payload[propertyType];
            if (properties) {
                Object.entries(properties).forEach(([propName, value]) => {
                    const typeData = format(value);
                    const typeFieldType = formatHS(typeData.type, typeData.fieldType);
                    if (typeFieldType === undefined) {
                        throw new actions_core_1.IntegrationError('Property type not supported', 'HUBSPOT_PROPERTY_TYPE_NOT_SUPPORTED', 400);
                    }
                    acc[propName] = {
                        name: propName,
                        type: typeData.type,
                        fieldType: typeData.fieldType,
                        typeFieldType
                    };
                });
            }
            return acc;
        }, {}));
    };
    const properties = extractProperties('properties');
    const sensitiveProperties = extractProperties('sensitive_properties');
    return {
        object_details: {
            object_type: objectType,
            id_field_name: payloads[0].object_details.id_field_name
        },
        properties,
        sensitiveProperties
    };
}
function format(value) {
    switch (typeof value) {
        case 'object':
            return { type: types_1.HSPropType.String, fieldType: types_1.HSPropFieldType.Text };
        case 'number':
            return { type: types_1.HSPropType.Number, fieldType: types_1.HSPropFieldType.Number };
        case 'boolean':
            return { type: types_1.HSPropType.Enumeration, fieldType: types_1.HSPropFieldType.BooleanCheckbox };
        case 'string': {
            const isoDateTimeRegex = /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])(?:([ T])(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;
            const dateOnlyRegex = /^\d{4}-\d{2}-\d{2}$/;
            if (isoDateTimeRegex.test(value)) {
                return {
                    type: dateOnlyRegex.test(value) ? types_1.HSPropType.Date : types_1.HSPropType.DateTime,
                    fieldType: types_1.HSPropFieldType.Date
                };
            }
            else {
                return { type: types_1.HSPropType.String, fieldType: types_1.HSPropFieldType.Text };
            }
        }
        case undefined:
        default:
            throw new actions_core_1.IntegrationError('Property must be an object, boolean, string or number', 'HUBSPOT_PROPERTY_VALUE_UNDEFINED', 400);
    }
}
function formatHS(type, fieldType) {
    if (type === 'date' && fieldType === 'date') {
        return types_1.HSPropTypeFieldType.DateDate;
    }
    else if (type === 'string' && fieldType === 'text') {
        return types_1.HSPropTypeFieldType.StringText;
    }
    else if (type === 'number' && fieldType === 'number') {
        return types_1.HSPropTypeFieldType.NumberNumber;
    }
    else if (type === 'datetime' && fieldType === 'date') {
        return types_1.HSPropTypeFieldType.DateTimeDate;
    }
    else if (type === 'enumeration' && fieldType === 'booleancheckbox') {
        return types_1.HSPropTypeFieldType.EnumerationBooleanCheckbox;
    }
    else if (type === 'string' && fieldType === 'textarea') {
        return types_1.HSPropTypeFieldType.StringTextArea;
    }
    return undefined;
}
function compareSchemas(schema1, schema2, statsContext) {
    if (schema2 === undefined) {
        return { match: 'no_match' };
    }
    if (schema1.object_details.object_type !== schema2.object_details.object_type) {
        statsContext?.statsClient?.incr('cache.compare.error1', 1, statsContext?.tags);
        throw new actions_core_1.PayloadValidationError("Hubspot.CustomObject.compareSchemas: Cache error - Schema object_type don't match");
    }
    if (schema1.object_details.id_field_name !== schema2.object_details.id_field_name) {
        statsContext?.statsClient?.incr('cache.compare.error2', 1, statsContext?.tags);
        throw new actions_core_1.PayloadValidationError("Hubspot.CustomObject.compareSchemas: Cache error - Schema id_field_name don't match");
    }
    const missingProps = [];
    const missingSensitiveProps = [];
    schema1.properties.forEach((prop1) => {
        if (!schema2.properties.some((prop2) => compareProps(prop1, prop2))) {
            missingProps.push(prop1);
        }
    });
    schema1.sensitiveProperties.forEach((prop1) => {
        if (!schema2.sensitiveProperties.some((prop2) => compareProps(prop1, prop2))) {
            missingSensitiveProps.push(prop1);
        }
    });
    return {
        match: missingProps.length > 0 || missingSensitiveProps.length > 0 ? 'properties_missing' : 'full_match',
        missingProperties: missingProps,
        missingSensitiveProperties: missingSensitiveProps
    };
}
function compareProps(prop1, prop2) {
    if (prop1.name === prop2.name) {
        if (prop1.type === prop2.type &&
            prop1.fieldType === prop2.fieldType &&
            prop1.typeFieldType === prop2.typeFieldType) {
            return true;
        }
        if (prop1.type === prop2.type &&
            prop2.fieldType === 'select' &&
            prop2.type === 'enumeration' &&
            prop1.fieldType === 'text' &&
            prop1.type === 'string') {
            return true;
        }
        if (prop1.type === prop2.type &&
            prop2.fieldType === 'textarea' &&
            prop2.type === 'string' &&
            prop1.fieldType === 'text' &&
            prop1.type === 'string') {
            return true;
        }
        throw new actions_core_1.IntegrationError(`Payload property with name ${prop1.name} has a different type to the property in HubSpot. Expected: type = ${prop1.type} fieldType = ${prop1.fieldType}. Received: type = ${prop2.type} fieldType = ${prop2.fieldType}`, 'HUBSPOT_PROPERTY_TYPE_MISMATCH', 400);
    }
    return false;
}
//# sourceMappingURL=schema-functions.js.map