import { LogStatus, GetProductionStatus } from '@memberjunction/core';
export function buildComponentProps(data = {}, userState = {}, utilities = {}, callbacks = {
    OpenEntityRecord: () => { },
    RegisterMethod: () => { },
    CreateSimpleNotification: () => { }
}, components = {}, styles, options = {}, onStateChanged) {
    const { validate = true, transformData, transformState, debounceUpdateUserState = 3000 } = options;
    const transformedData = transformData ? transformData(data) : data;
    const transformedState = transformState ? transformState(userState) : userState;
    const props = {
        data: transformedData,
        userState: transformedState,
        utilities,
        callbacks: normalizeCallbacks(callbacks, debounceUpdateUserState),
        components,
        styles: normalizeStyles(styles),
        onStateChanged
    };
    if (validate) {
        validateComponentProps(props);
    }
    return props;
}
const updateUserStateSubjects = new WeakMap();
const updateUserStateSubscriptions = new WeakMap();
const loopDetectionStates = new WeakMap();
function deepEqual(obj1, obj2) {
    if (obj1 === obj2)
        return true;
    if (!obj1 || !obj2)
        return false;
    if (typeof obj1 !== 'object' || typeof obj2 !== 'object')
        return false;
    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);
    if (keys1.length !== keys2.length)
        return false;
    for (const key of keys1) {
        if (!keys2.includes(key))
            return false;
        if (!deepEqual(obj1[key], obj2[key]))
            return false;
    }
    return true;
}
export function normalizeCallbacks(callbacks, debounceMs = 3000) {
    const normalized = {
        OpenEntityRecord: callbacks?.OpenEntityRecord || (() => { }),
        RegisterMethod: callbacks?.RegisterMethod || (() => { }),
        CreateSimpleNotification: callbacks?.CreateSimpleNotification || (() => { })
    };
    if (callbacks) {
        Object.keys(callbacks).forEach(key => {
            if (typeof callbacks[key] === 'function' && !normalized.hasOwnProperty(key)) {
                normalized[key] = callbacks[key];
            }
        });
    }
    return normalized;
}
export function normalizeStyles(styles) {
    return styles;
}
export function validateComponentProps(props) {
    if (props.data === null || props.data === undefined) {
        throw new Error('Component props.data cannot be null or undefined');
    }
    if (props.userState === null) {
        throw new Error('Component props.userState cannot be null');
    }
    if (props.utilities === null) {
        throw new Error('Component props.utilities cannot be null');
    }
    if (!props.callbacks || typeof props.callbacks !== 'object') {
        throw new Error('Component props.callbacks must be an object');
    }
    for (const [key, value] of Object.entries(props.callbacks)) {
        if (value !== undefined && typeof value !== 'function') {
            throw new Error(`Component callback "${key}" must be a function`);
        }
    }
}
export function mergeProps(...propsList) {
    const merged = {
        data: {},
        userState: {},
        utilities: {},
        callbacks: {},
        components: {},
        styles: {}
    };
    for (const props of propsList) {
        if (props.data) {
            merged.data = { ...merged.data, ...props.data };
        }
        if (props.userState) {
            merged.userState = { ...merged.userState, ...props.userState };
        }
        if (props.utilities) {
            merged.utilities = { ...merged.utilities, ...props.utilities };
        }
        if (props.callbacks) {
            merged.callbacks = { ...merged.callbacks, ...props.callbacks };
        }
        if (props.components) {
            merged.components = { ...merged.components, ...props.components };
        }
        if (props.styles) {
            merged.styles = { ...merged.styles, ...props.styles };
        }
    }
    return merged;
}
export function createPropsTransformer(transformations) {
    return (props) => {
        const transformed = { ...props };
        for (const [path, transformer] of Object.entries(transformations)) {
            const pathParts = path.split('.');
            let current = transformed;
            for (let i = 0; i < pathParts.length - 1; i++) {
                if (!current[pathParts[i]]) {
                    current[pathParts[i]] = {};
                }
                current = current[pathParts[i]];
            }
            const lastPart = pathParts[pathParts.length - 1];
            if (current[lastPart] !== undefined) {
                current[lastPart] = transformer(current[lastPart]);
            }
        }
        return transformed;
    };
}
export function wrapCallbacksWithLogging(callbacks, componentName) {
    const wrapped = {
        OpenEntityRecord: callbacks?.OpenEntityRecord || (() => { }),
        RegisterMethod: callbacks?.RegisterMethod || (() => { }),
        CreateSimpleNotification: callbacks?.CreateSimpleNotification || (() => { })
    };
    Object.keys(callbacks).forEach(key => {
        if (key !== 'OpenEntityRecord' && key !== 'RegisterMethod' && key !== 'CreateSimpleNotification' && typeof callbacks[key] === 'function') {
            wrapped[key] = (...args) => {
                if (!GetProductionStatus()) {
                    LogStatus(`[${componentName}] ${key} called with args:`, undefined, args);
                }
                return callbacks[key](...args);
            };
        }
    });
    if (callbacks.OpenEntityRecord) {
        wrapped.OpenEntityRecord = (entityName, key) => {
            if (!GetProductionStatus()) {
                LogStatus(`[${componentName}] OpenEntityRecord called:`, undefined, { entityName, key });
            }
            callbacks.OpenEntityRecord(entityName, key);
        };
    }
    if (callbacks.RegisterMethod) {
        wrapped.RegisterMethod = (methodName, handler) => {
            if (!GetProductionStatus()) {
                LogStatus(`[${componentName}] RegisterMethod called for:`, undefined, methodName);
            }
            callbacks.RegisterMethod(methodName, handler);
        };
    }
    if (callbacks.CreateSimpleNotification) {
        wrapped.CreateSimpleNotification = (message, style, hideAfter) => {
            if (!GetProductionStatus()) {
                LogStatus(`[${componentName}] CreateSimpleNotification called:`, undefined, { message, style, hideAfter });
            }
            callbacks.CreateSimpleNotification(message, style, hideAfter);
        };
    }
    return wrapped;
}
export function extractPropPaths(componentCode) {
    const paths = [];
    const patterns = [
        /props\.data\.(\w+)/g,
        /props\.userState\.(\w+)/g,
        /props\.utilities\.(\w+)/g,
        /props\.callbacks\.(\w+)/g
    ];
    for (const pattern of patterns) {
        let match;
        while ((match = pattern.exec(componentCode)) !== null) {
            paths.push(match[0]);
        }
    }
    return [...new Set(paths)];
}
//# sourceMappingURL=prop-builder.js.map