"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateScenarios = validateScenarios;
const mablApiClientFactory_1 = require("@mablhq-internal/runtime/api/mablApiClientFactory");
const cliUtil_1 = require("@mablhq-internal/runtime/core/cliUtil");
const constants_1 = require("@mablhq-internal/runtime/core/constants");
const constants_2 = require("../../constants");
const datatableUtil_1 = require("@mablhq-internal/runtime/util/datatableUtil");
const mablscriptFind_1 = require("@mablhq/test-model/mablscriptFind");
const logUtils_1 = require("@mablhq-internal/runtime/util/logUtils");
const pureUtil_1 = require("@mablhq-internal/runtime/util/pureUtil");
exports.command = `update <${constants_1.CommandArgId}> <${constants_2.CommandArgInput}>`;
exports.describe = 'Update a mabl DataTable';
exports.builder = (yargs) => {
    yargs
        .positional(constants_1.CommandArgId, {
        describe: 'ID of DataTable to update',
        type: 'string',
    })
        .positional(constants_2.CommandArgInput, {
        alias: 'file',
        describe: 'Relative path file to create DataTable from',
    })
        .option(constants_1.CommandArgWorkspaceId, {
        alias: constants_2.CommandArgAliases.WorkspaceId,
        describe: `Workspace your DataTable is exists in`,
        type: 'string',
    })
        .option(constants_1.CommandArgFormat, {
        alias: 'fmt',
        demandOption: false,
        describe: `Specify the format of your input file (checks file extension type by default)`,
        choices: [constants_1.OutputFormats.Json, constants_1.OutputFormats.Csv],
    });
};
exports.handler = (0, cliUtil_1.failWrapper)(updateDataTable);
function validateScenarios(scenarios, dataTable) {
    if (!scenarios || scenarios.length === 0) {
        throw Error('Must have at least 1 scenario in DataTable.');
    }
    const validationVariables = scenarios[0].variables;
    scenarios.forEach((scenario) => {
        if (scenario.id && !dataTable.scenario_ids?.includes(scenario.id)) {
            throw Error(`Scenario in input with ID ${scenario.id} does not exist in DataTable scenario_ids.`);
        }
        if (!scenario.variables || scenario.variables.length === 0) {
            throw Error('Must have at least 1 variable in a scenario.');
        }
        if (scenario.variables.length !== validationVariables?.length) {
            throw Error('All scenarios must have the same number of variables.');
        }
        scenario.variables?.forEach((variable, index) => {
            if (!(0, mablscriptFind_1.isValidUserVariableName)(variable.name)) {
                throw Error(`Invalid variable name: ${variable.name}. Variable names must start with a letter or underscore (_) followed by letters, numbers, and underscores and cannot be "user", "web", or "mail"`);
            }
            if (variable.name !== validationVariables[index].name) {
                throw Error('All scenarios must have the same variable names and be in the same order.');
            }
        });
    });
}
async function updateDataTable(parsed) {
    const { id: dataTableId, input } = parsed;
    const format = parsed.format ?? (0, datatableUtil_1.inferFileFormat)(input);
    const apiClient = await mablApiClientFactory_1.MablApiClientFactory.createApiClient();
    const dataTable = await apiClient.getDataTable(dataTableId);
    let scenarios;
    switch (format) {
        case constants_1.OutputFormats.Json:
            scenarios = (0, datatableUtil_1.parseJsonScenarios)(input);
            break;
        case constants_1.OutputFormats.Csv:
            scenarios = await (0, datatableUtil_1.parseCsvScenarios)(input);
            break;
        default:
            throw Error(`${format} is not a valid option.`);
    }
    validateScenarios(scenarios, dataTable);
    const scenariosToUpdate = scenarios.filter((scenario) => scenario.id !== undefined);
    const scenariosToCreate = scenarios.filter((scenario) => scenario.id === undefined);
    const inputScenarioIds = new Set(scenariosToUpdate.map((scenario) => scenario.id));
    const scenarioIdsToRemove = (dataTable.scenario_ids ?? []).filter((id) => !inputScenarioIds.has(id));
    const updateResults = await Promise.allSettled(scenariosToUpdate.map((scenario) => apiClient.putScenario(scenario.id, scenario)));
    (0, logUtils_1.logPromiseSettledRejections)(updateResults);
    const createResults = await Promise.allSettled(scenariosToCreate.map((scenario) => apiClient.createScenario(dataTableId, scenario)));
    (0, logUtils_1.logPromiseSettledRejections)(createResults);
    const removeResults = await Promise.allSettled(scenarioIdsToRemove.map((scenarioId) => apiClient.removeScenario(scenarioId)));
    (0, logUtils_1.logPromiseSettledRejections)(removeResults);
    if (updateResults.some(pureUtil_1.isRejectedPromise) ||
        createResults.some(pureUtil_1.isRejectedPromise) ||
        removeResults.some(pureUtil_1.isRejectedPromise)) {
        throw new Error('Some DataTable operations failed. See above for details.');
    }
}
