"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createUpdateWorkflowTool = void 0;
const db_1 = require("@n8n/db");
const zod_1 = __importDefault(require("zod"));
const mcp_constants_1 = require("../../mcp.constants");
const constants_1 = require("./constants");
const credentials_auto_assign_1 = require("./credentials-auto-assign");
const workflow_helpers_1 = require("../../../../workflow-helpers");
const workflow_validation_utils_1 = require("../workflow-validation.utils");
const inputSchema = {
    workflowId: zod_1.default.string().describe('The ID of the workflow to update'),
    code: zod_1.default
        .string()
        .describe(`Full TypeScript/JavaScript workflow code using the n8n Workflow SDK. Must be validated first with ${constants_1.CODE_BUILDER_VALIDATE_TOOL.toolName}.`),
    name: zod_1.default
        .string()
        .max(128)
        .optional()
        .describe('Optional workflow name. If not provided, uses the name from the code.'),
    description: zod_1.default
        .string()
        .max(255)
        .optional()
        .describe('Short workflow description summarizing what it does (1-2 sentences, max 255 chars).'),
};
const outputSchema = {
    workflowId: zod_1.default.string().describe('The ID of the updated workflow'),
    name: zod_1.default.string().describe('The name of the updated workflow'),
    nodeCount: zod_1.default.number().describe('The number of nodes in the workflow'),
    url: zod_1.default.string().describe('The URL to open the workflow in n8n'),
    autoAssignedCredentials: zod_1.default
        .array(zod_1.default.object({
        nodeName: zod_1.default.string().describe('The name of the node that had credentials auto-assigned'),
        credentialName: zod_1.default.string().describe('The name of the credential that was auto-assigned'),
    }))
        .describe('List of credentials that were automatically assigned to nodes'),
    note: zod_1.default
        .string()
        .optional()
        .describe('Additional notes about the workflow update, such as any nodes that were skipped during credential auto-assignment.'),
};
const createUpdateWorkflowTool = (user, workflowFinderService, workflowService, urlService, telemetry, nodeTypes, credentialsService, sharedWorkflowRepository) => ({
    name: constants_1.MCP_UPDATE_WORKFLOW_TOOL.toolName,
    config: {
        description: `Update an existing workflow in n8n from validated SDK code. Parses the code into a workflow and saves the changes. Always validate with ${constants_1.CODE_BUILDER_VALIDATE_TOOL.toolName} first.`,
        inputSchema,
        outputSchema,
        annotations: {
            title: constants_1.MCP_UPDATE_WORKFLOW_TOOL.displayTitle,
            readOnlyHint: false,
            destructiveHint: true,
            idempotentHint: true,
            openWorldHint: false,
        },
    },
    handler: async ({ workflowId, code, name, description, }) => {
        const telemetryPayload = {
            user_id: user.id,
            tool_name: constants_1.MCP_UPDATE_WORKFLOW_TOOL.toolName,
            parameters: { workflowId, codeLength: code.length, hasName: !!name },
        };
        try {
            const existingWorkflow = await (0, workflow_validation_utils_1.getMcpWorkflow)(workflowId, user, ['workflow:update'], workflowFinderService);
            const { ParseValidateHandler, stripImportStatements } = await Promise.resolve().then(() => __importStar(require('@n8n/ai-workflow-builder')));
            const handler = new ParseValidateHandler({ generatePinData: false });
            const strippedCode = stripImportStatements(code);
            const result = await handler.parseAndValidate(strippedCode);
            const workflowJson = result.workflow;
            const workflowUpdateData = new db_1.WorkflowEntity();
            Object.assign(workflowUpdateData, {
                name: name ?? workflowJson.name,
                ...(description !== undefined ? { description } : {}),
                nodes: workflowJson.nodes,
                connections: workflowJson.connections,
                pinData: workflowJson.pinData,
                meta: { ...workflowJson.meta, aiBuilderAssisted: true },
            });
            (0, workflow_helpers_1.resolveNodeWebhookIds)(workflowUpdateData, nodeTypes);
            (0, credentials_auto_assign_1.stripNullCredentialStubs)(workflowUpdateData.nodes);
            const existingCredsByNode = new Map(existingWorkflow.nodes.map((n) => [n.name, { type: n.type, credentials: n.credentials }]));
            for (const node of workflowUpdateData.nodes) {
                if (!node.credentials) {
                    const existing = existingCredsByNode.get(node.name);
                    if (existing?.type === node.type && existing.credentials) {
                        node.credentials = { ...existing.credentials };
                    }
                }
            }
            const sharedWorkflow = await sharedWorkflowRepository.findOneOrFail({
                where: { workflowId, role: 'workflow:owner' },
                select: ['projectId'],
            });
            const { assignments: credentialAssignments, skippedHttpNodes } = await (0, credentials_auto_assign_1.autoPopulateNodeCredentials)(workflowUpdateData, user, nodeTypes, credentialsService, sharedWorkflow.projectId);
            const updatedWorkflow = await workflowService.update(user, workflowUpdateData, workflowId, {
                aiBuilderAssisted: true,
            });
            const baseUrl = urlService.getInstanceBaseUrl();
            const workflowUrl = `${baseUrl}/workflow/${updatedWorkflow.id}`;
            telemetryPayload.results = {
                success: true,
                data: {
                    workflowId: updatedWorkflow.id,
                    nodeCount: updatedWorkflow.nodes.length,
                },
            };
            telemetry.track(mcp_constants_1.USER_CALLED_MCP_TOOL_EVENT, telemetryPayload);
            const output = {
                workflowId: updatedWorkflow.id,
                name: updatedWorkflow.name,
                nodeCount: updatedWorkflow.nodes.length,
                url: workflowUrl,
                autoAssignedCredentials: credentialAssignments,
                note: skippedHttpNodes.length
                    ? `HTTP Request nodes (${skippedHttpNodes.join(', ')}) were skipped during credential auto-assignment. Their credentials must be configured manually.`
                    : undefined,
            };
            return {
                content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
                structuredContent: output,
            };
        }
        catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            telemetryPayload.results = {
                success: false,
                error: errorMessage,
            };
            telemetry.track(mcp_constants_1.USER_CALLED_MCP_TOOL_EVENT, telemetryPayload);
            const output = { error: errorMessage };
            return {
                content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
                structuredContent: output,
                isError: true,
            };
        }
    },
});
exports.createUpdateWorkflowTool = createUpdateWorkflowTool;
//# sourceMappingURL=update-workflow.tool.js.map