Source: Router/actionTemplate/helpers.js

/**
 * Helper functions for Action Template operations
 */

/**
 * Recursively builds a translation object by extracting content and label properties 
 * from a serialized input object and its nested children. Ensures that existing entries 
 * in the translation object are not overridden.
 *
 * @param {Object} serialized - The input object containing components and their properties.
 * @param {Object} translateObject - The object to store translations, mapping keys to values.
 *
 * @example
 * const serialized = {
 *   component1: {
 *     paras: { content: "Hello", label: "Greeting" },
 *     children: [
 *       { component2: { paras: { content: "World", label: "Planet" } } }
 *     ]
 *   }
 * };
 * const translateObject = {};
 * buildTranslateObject(serialized, translateObject);
 * console.log(translateObject); // { Hello: "Hello", Greeting: "Greeting", World: "World", Planet: "Planet" }
 */
export const buildTranslateObject = (serialized, translateObject) => {
    const [[component, componentObject]] = Object.entries(serialized);

    if (componentObject.paras) {
        const paras = componentObject.paras;
        if (paras.content)
            translateObject[paras.content] = translateObject[paras.content] ? translateObject[paras.content] : paras.content;   // do not override existing entries
        if (paras.label)
            translateObject[paras.label] = translateObject[paras.label] ? translateObject[paras.label] : paras.label;   // do not override existing entries
    }
    
    if (componentObject.children) {
        const children = componentObject.children;
        // now call it for further content
        if (Array.isArray(children)) {
            children.forEach((c, Index) => {
                buildTranslateObject(c, translateObject);
            });
        }
        else if (typeof children === 'object')
            buildTranslateObject(children, translateObject);
    }
};

/**
 * Validates input for register endpoint
 * @param {Object} body - Request body
 * @returns {Object} Validation result with success flag and message
 */
export const validateRegisterInput = (body) => {
    const { botUID, organizationUIDs = [], template = {} } = body;

    if (!botUID || !botUID.match(/^UUID\-[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-5][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}/)) {
        return {
            success: false,
            message: 'botUID is required in the UUID format'
        };
    }

    if (!Array.isArray(organizationUIDs) ) {
        return {
            success: false,
            message: 'organizationUIDs must be an array'
        };
    }

    if (organizationUIDs.length === 0) {
        return {
            success: false,
            message: 'organizationUIDs array cannot be empty'
        };
    }

    if (!template) {
        return {
            success: false,
            message: 'template cannot be empty'
        };
    }

    if(!template.UID) {
        return {
            success: false,
            message: 'template.UID is required'
        };
    }

    if(template.sortIndex === undefined || isNaN(parseInt(template.sortIndex))) {
        return {
            success: false,
            message: 'template.sortIndex must be defined and must be a valid number'
        };
    }

    return { success: true };
};

/**
 * Merges existing template data with new data, preserving customizations
 * @param {Object} templateData - New template data
 * @param {Object} existingData - Existing template data
 * @returns {Object} Merged data
 */
export const mergeTemplateData = (templateData, existingData) => {
    const Data = {
        ...templateData,
        translate: existingData.translate,
        name: existingData.name || templateData.name,
        description: existingData.description || templateData.description
    };

    if (templateData.defaults && existingData.defaults) {
        Object.entries(existingData.defaults).forEach(([key, text]) => {
            Data.defaults[key] = text;
        });
    } else if (existingData.defaults) {
        Data.defaults = existingData.defaults;
    }

    return Data;
};