"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.API_CREDENTIALS_PASSWORD_VARIABLE_NAME = exports.API_CREDENTIALS_USERNAME_VARIABLE_NAME = exports.API_CREDENTIALS_NAMESPACE = exports.API_URL_VARIABLE_NAME = void 0;
exports.convertVariablesToPostmanFormat = convertVariablesToPostmanFormat;
exports.generateVariablesSummaryForImport = generateVariablesSummaryForImport;
exports.generateVariablesSummaryForExport = generateVariablesSummaryForExport;
exports.addFlowNamespace = addFlowNamespace;
exports.addUserNamespace = addUserNamespace;
exports.findUsedVariables = findUsedVariables;
const mablscriptFind_1 = require("@mablhq/test-model/mablscriptFind");
const variable_constants_1 = require("./variable-constants");
exports.API_URL_VARIABLE_NAME = `${variable_constants_1.API_NAMESPACE}url`;
exports.API_CREDENTIALS_NAMESPACE = `${variable_constants_1.API_NAMESPACE}credentials.`;
exports.API_CREDENTIALS_USERNAME_VARIABLE_NAME = `${exports.API_CREDENTIALS_NAMESPACE}username`;
exports.API_CREDENTIALS_PASSWORD_VARIABLE_NAME = `${exports.API_CREDENTIALS_NAMESPACE}password`;
function convertVariablesToPostmanFormat(value) {
    return value?.replace(/{{@([^{}]+)}}/g, '{{$1}}');
}
function generateVariablesSummaryForImport(variableSources) {
    const { environment, scenario, url, credentials, plan, flow, journeyRun, previousFlowVariables, flowConfiguration, test, } = variableSources;
    const summary = {
        dataDriven: {},
        effective: {},
        environment: {},
        flow: {},
        journey: {},
        parameters: {},
    };
    test?.variables?.inputs?.forEach((variable) => {
        const name = removeUserNamespace(variable.name);
        const value = variable.default_value;
        summary.journey[name] = value;
        summary.effective[name] = value;
    });
    const environmentVariables = environment?.variables || {};
    Object.entries(environmentVariables).forEach(([key, value]) => {
        const name = removeUserNamespace(key);
        summary.environment[name] = value;
        summary.effective[name] = value;
    });
    const planParameters = extractValueParameters(plan?.parameters);
    planParameters.forEach((parameter) => {
        const name = removeUserNamespace(parameter.name);
        const { value } = parameter;
        summary.parameters[name] = value;
        summary.effective[name] = value;
    });
    const journeyParameters = extractValueParameters(journeyRun &&
        plan?.execution_stages?.[journeyRun.stage_index]?.journeys?.find((journey) => journey.journey_id)?.parameters);
    journeyParameters.forEach((parameter) => {
        const name = removeUserNamespace(parameter.name);
        const { value } = parameter;
        summary.parameters[name] = value;
        summary.effective[name] = value;
    });
    const journeyInputs = journeyRun?.journey_parameters?.imported_variables || {};
    Object.entries(journeyInputs).forEach(([key, value]) => {
        const name = removeUserNamespace(key);
        summary.journey[name] = value;
        summary.effective[name] = value;
    });
    const ddtVariables = journeyRun?.journey_parameters?.user_variables?.row ||
        scenario?.variables ||
        [];
    ddtVariables.forEach((variable) => {
        const name = removeUserNamespace(variable.name);
        const { value } = variable;
        const convertedValue = convertVariablesToPostmanFormat(value);
        summary.dataDriven[name] = convertedValue;
        summary.effective[name] = convertedValue;
    });
    const exportedVariables = previousFlowVariables || {};
    Object.entries(exportedVariables).forEach(([key, value]) => {
        const name = removeUserNamespace(key);
        summary.dataDriven[name] = value;
        summary.effective[name] = value;
    });
    flow?.parameters?.forEach((parameter) => {
        const name = removeFlowNamespace(parameter.name);
        const value = flowConfiguration?.parameters?.[parameter.name] ??
            parameter.default_value;
        summary.flow[name] = value;
        summary.effective[addFlowNamespace(name)] = value;
    });
    if (url) {
        summary.effective[exports.API_URL_VARIABLE_NAME] = url;
    }
    if (credentials) {
        summary.effective[exports.API_CREDENTIALS_USERNAME_VARIABLE_NAME] =
            credentials.properties?.username;
        summary.effective[exports.API_CREDENTIALS_PASSWORD_VARIABLE_NAME] =
            credentials.properties?.password;
    }
    return summary;
}
function generateVariablesSummaryForExport(testContext, plan, test, flow, journeyRun, exportedVariables) {
    return normalizeVariablesSummaryForExport(generateVariablesSummaryForImport({
        environment: testContext.environment,
        url: testContext.url,
        credentials: testContext.credentials,
        scenario: testContext.getScenario(),
        plan,
        flow,
        journeyRun,
        previousFlowVariables: exportedVariables,
        test,
    }));
}
function normalizeVariablesSummaryForExport(summary) {
    return {
        dataDriven: addUserNamespaceToVariableNames(sanitizeVariables(summary.dataDriven)),
        effective: sanitizeVariables(summary.effective),
        environment: addUserNamespaceToVariableNames(sanitizeVariables(summary.environment)),
        flow: addFlowNamespaceToVariableNames(sanitizeVariables(summary.flow)),
        journey: addUserNamespaceToVariableNames(sanitizeVariables(summary.journey)),
        parameters: addUserNamespaceToVariableNames(sanitizeVariables(summary.parameters)),
        ...(summary.stepSources && { stepSources: summary.stepSources }),
    };
}
function sanitizeVariables(variables) {
    const sanitizedVariables = {};
    Object.keys(variables)
        .filter((name) => (0, mablscriptFind_1.isValidUserVariableName)(name))
        .forEach((name) => (sanitizedVariables[name] = variables[name]));
    return sanitizedVariables;
}
function addFlowNamespaceToVariableNames(variables) {
    return addPrefixToVariableNames(variables, variable_constants_1.FLOW_NAMESPACE);
}
function addUserNamespaceToVariableNames(variables) {
    return addPrefixToVariableNames(variables, variable_constants_1.USER_NAMESPACE);
}
function addPrefixToVariableNames(variables, prefix) {
    return mapVariables(variables, (variable) => ({
        name: addPrefix(variable.name, prefix),
        value: variable.value,
    }));
}
function mapVariables(variables, mapper) {
    const mappedVariables = {};
    Object.keys(variables)
        .map((name) => mapper({ name, value: variables[name] }))
        .forEach((variable) => (mappedVariables[variable.name] = variable.value));
    return mappedVariables;
}
function extractValueParameters(parameters) {
    if (!parameters) {
        return [];
    }
    return parameters.filter((parameter) => parameter.type?.toString() === 'value');
}
function removeFlowNamespace(variableName) {
    return removePrefix(variableName, variable_constants_1.FLOW_NAMESPACE);
}
function removeUserNamespace(variableName) {
    return removePrefix(variableName, variable_constants_1.USER_NAMESPACE);
}
function removePrefix(variableName, prefix) {
    if (variableName.startsWith(prefix)) {
        return variableName.substring(prefix.length);
    }
    return variableName;
}
function addFlowNamespace(variableName) {
    return addPrefix(variableName, variable_constants_1.FLOW_NAMESPACE);
}
function addUserNamespace(variableName) {
    return addPrefix(variableName, variable_constants_1.USER_NAMESPACE);
}
function addPrefix(variableName, prefix) {
    if (variableName.startsWith(prefix)) {
        return variableName;
    }
    return `${prefix}${variableName}`;
}
function findUsedVariables(collection, variableNames) {
    const collectionSubset = {
        auth: collection.auth,
        item: collection.item,
        event: collection.event,
    };
    const collectionAsJson = JSON.stringify(collectionSubset);
    return variableNames.filter((variableName) => collectionAsJson.includes(variableName));
}
