"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.databaseQueryExecutor = void 0;
const toolExecutor_types_1 = require("../toolExecutor-types");
const DatabaseQueryStep_1 = __importDefault(require("../../sharedUtils/mablscript/canonical/DatabaseQueryStep"));
const mablscriptFind_1 = require("@mablhq/test-model/mablscriptFind");
const mablApi_1 = require("../../../mablApi");
const variable_constants_1 = require("../../sharedUtils/variable-constants");
exports.databaseQueryExecutor = {
    needsFind: () => false,
    getStepType: () => mablApi_1.ExecuteToolName.DatabaseQuery,
    execute: async (payload, stateProvider, eventHandler, logger) => {
        const toolParams = payload.toolCall
            .toolParams;
        try {
            let snippetDescriptor;
            let reusableSnippet;
            const rawType = toolParams.type;
            if (rawType !== 'inline' && rawType !== 'reusable') {
                return {
                    success: false,
                    errorMessage: `Invalid 'type' value '${String(rawType)}'. Use 'inline' for a one-shot SQL query, or 'reusable' to reference an existing workspace snippet.`,
                };
            }
            if (toolParams.type === 'reusable') {
                if (typeof toolParams.snippet_id !== 'string' ||
                    toolParams.snippet_id.length === 0) {
                    return {
                        success: false,
                        errorMessage: "When type='reusable', 'snippet_id' is required. Discover candidate snippets via request_snippet_tools with snippet_types: ['sql'], or switch to type='inline' with database_connection_id + query.",
                    };
                }
                const snippet = await stateProvider.getSnippet(toolParams.snippet_id);
                if (!snippet) {
                    return {
                        success: false,
                        errorMessage: `Snippet with ID ${toolParams.snippet_id} not found in this workspace; verify the snippet_id via request_snippet_tools (with snippet_types: ["sql"]) or switch to an inline query.`,
                    };
                }
                if (!snippet.id || !snippet.invariant_id) {
                    return {
                        success: false,
                        errorMessage: `Snippet ${toolParams.snippet_id} is a legacy snippet without a snippet_id; please re-save it in the web editor before using it in a database_query step.`,
                    };
                }
                eventHandler.registerSnippet(snippet);
                const overrides = toolParams.parameter_overrides ?? {};
                const parameterOverrides = Object.entries(overrides)
                    .map(([paramName, value]) => {
                    const snippetParameter = snippet.parameters?.find((param) => param.name === paramName);
                    if (!snippetParameter) {
                        logger.warn(`Snippet parameter '${paramName}' not found in snippet ${toolParams.snippet_id}`);
                        return undefined;
                    }
                    return { id: snippetParameter.id, value: String(value) };
                })
                    .filter((override) => override !== undefined);
                const reusableDescriptor = {
                    snippetId: snippet.id,
                    snippetInvariantId: snippet.invariant_id,
                    parameterOverrides,
                };
                snippetDescriptor = reusableDescriptor;
                reusableSnippet = snippet;
            }
            else {
                if (typeof toolParams.database_connection_id !== 'string' ||
                    toolParams.database_connection_id.length === 0) {
                    return {
                        success: false,
                        errorMessage: "When type='inline', 'database_connection_id' is required. Pick a connection that exists in the workspace; do not invent one.",
                    };
                }
                if (typeof toolParams.query !== 'string' ||
                    toolParams.query.length === 0) {
                    return {
                        success: false,
                        errorMessage: "When type='inline', 'query' is required (the SQL to execute).",
                    };
                }
                const inlineDescriptor = {
                    inlineSnippet: {
                        name: toolParams.snippet_name?.trim() ||
                            deriveInlineSnippetName(toolParams.query),
                        body: toolParams.query,
                        database_connection_id: toolParams.database_connection_id,
                        snippet_type: mablApi_1.SnippetTypeEnum.Sql,
                        parameters: [],
                    },
                    parameterOverrides: [],
                };
                snippetDescriptor = inlineDescriptor;
            }
            const queryAssertions = toolParams.assertions?.map((assertion) => ({
                source: assertion.source,
                target: assertion.target,
                assertion: assertion.assertion,
                value: assertion.value,
            }));
            const queryVariables = toolParams.variables?.map((variable) => ({
                source: variable.source,
                target: variable.target,
                name: variable.name,
            }));
            const descriptor = {
                snippet: snippetDescriptor,
                assertions: queryAssertions,
                variables: queryVariables,
                options: undefined,
            };
            const recordedVariables = (queryVariables ?? []).map((variable) => ({
                variableType: mablscriptFind_1.VariableType.DATABASE,
                name: `user.${variable.name}`,
                humanizedName: variable.name,
                value: variable_constants_1.EMPTY_VARIABLE_VALUE_PLACEHOLDER,
                query: descriptor,
            }));
            for (const variable of recordedVariables) {
                eventHandler.saveVariable(variable);
            }
            const step = DatabaseQueryStep_1.default.create({
                snippetDescriptor,
                queryAssertions,
                queryVariables,
                stepOptions: undefined,
                queryResult: undefined,
                variables: recordedVariables,
                snippet: reusableSnippet,
            });
            return (0, toolExecutor_types_1.recordStepAndTrackResult)(() => Promise.resolve({ steps: [step], stepsToReplay: 1, step }), 0, stateProvider, eventHandler, logger);
        }
        catch (error) {
            logger.error('Error executing database_query tool:', error);
            return {
                success: false,
                errorMessage: error instanceof Error ? error.message : 'Unknown error',
            };
        }
    },
};
function deriveInlineSnippetName(query) {
    const truncated = query.trim().replace(/\s+/g, ' ').slice(0, 60);
    return truncated.length > 0 ? `Inline SQL: ${truncated}` : 'Inline SQL query';
}
