"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mcpMablTool_1 = require("./mcpMablTool");
const zod_1 = require("zod");
const trainingSessions_1 = require("@mablhq-internal/runtime/core/trainer/trainingSessions");
const messaging_1 = require("@mablhq-internal/runtime/core/messaging/messaging");
const mablApi_1 = require("@mablhq-internal/runtime/mablApi");
const common_1 = require("../utils/common");
const featureSet_1 = require("@mablhq-internal/runtime/api/featureSet");
const testUtils_1 = require("../utils/testUtils");
const uuid_1 = require("uuid");
const baseFields = {
    applicationId: zod_1.z
        .string()
        .describe('The id of the application to run the test in'),
    environmentId: zod_1.z
        .string()
        .describe('The id of the environment to run the test in'),
    url: zod_1.z.string().describe(`The url to test:
          If you are testing a browser test, this will be the url of the application to test.
          On API tests this will be the endpoint to test.
          Try to validate that the url is correct.
          `),
    credentialsId: zod_1.z
        .string()
        .describe('Optional. The id of the credentials to use for training the test. Cloud type credentials are not valid here. If not provided, the user will be prompted to select from available non-cloud credentials.')
        .optional(),
    withoutCredentials: zod_1.z
        .boolean()
        .describe('Optional. If true, the test will be created without credentials. If false, the user will be prompted to select from available non-cloud credentials.')
        .optional(),
    name: zod_1.z.string().describe('The name of the test'),
    intent: zod_1.z.string().describe(`The intent of the test.
          Be as detailed as possible.
          If you are given a ticket, provide the intent based on the ticket.
          If you are not working on a ticket, provide the intent based on the changes you made to the code.
          `),
    issueOrTicket: zod_1.z
        .string()
        .describe('The issue or ticket description that is being worked on. This will be used to generate the intent.'),
    steps: zod_1.z.string().describe(`List of steps to accomplish the intent. Put each step in a new line.
          If you are testing an API, include data to be sent in the request and the expected response.
          `),
    intentUrl: zod_1.z
        .string()
        .describe('Optional URL to be included in the intent')
        .optional(),
};
const inputSchema = zod_1.z
    .object({
    ...baseFields,
    isApiTest: zod_1.z
        .boolean()
        .describe('Set to true when the user explicitly requests an API test, mentions an API endpoint, OpenAPI spec, or Postman collection. Otherwise set to false.'),
    apiSpec: zod_1.z
        .string()
        .describe(`The API spec describing the endpoint(s) under test. Required when isApiTest=true. Provide an OpenAPI/Swagger spec, Postman collection, or a focused natural-language description of the endpoint, request body, and expected response.`)
        .optional(),
})
    .superRefine((data, ctx) => {
    if (data.isApiTest && !data.apiSpec) {
        ctx.addIssue({
            code: zod_1.z.ZodIssueCode.custom,
            message: 'apiSpec is required when isApiTest is true',
            path: ['apiSpec'],
        });
    }
});
const createMablTest = (0, mcpMablTool_1.defineTool)({
    schema: {
        name: 'create_mabl_test',
        title: 'Create a mabl test',
        description: 'Create a new browser or API test according to your provided prompt. ' +
            'Use isApiTest=false to create a browser test that drives a browser, web app, or native UI. ' +
            'Use isApiTest=true when the user explicitly requests an API test, mentions an API endpoint, ' +
            'an OpenAPI/Swagger spec, or a Postman collection — provide the spec via apiSpec. ' +
            'Example: Create a new mabl test based on these details. Use the application MyApplication in environment Development.',
        inputSchema,
        type: 'destructive',
    },
    handle: async (params, context) => {
        const { mablApiClient, workspaceId } = context.getCurrentContext();
        if (!context.featureIsAvailable(featureSet_1.GENERATIVE_AI_FEATURE_FLAG)) {
            return (0, common_1.stringToToolResult)('Generative AI is not available for your account. Please contact your workspace owner or mabl support for assistance in activating this feature.', true);
        }
        if (!params.url) {
            return (0, common_1.stringToToolResult)('url is required when creating a test. Try to infer the url from the user context or request the URL explicitly.', true);
        }
        if (!params.applicationId) {
            return (0, common_1.stringToToolResult)('applicationId is required when creating a test. Try to infer the application from the user context or request the application explicitly.', true);
        }
        if (!params.environmentId) {
            return (0, common_1.stringToToolResult)('environmentId is required when creating a test. Request the environment explicitly.', true);
        }
        const allCredentials = await mablApiClient.getCredentials(workspaceId, 500);
        const nonCloudCredentials = allCredentials.filter((credential) => !credential.cloud_only);
        if (params.credentialsId) {
            const selectedCredential = allCredentials.find((cred) => cred.id === params.credentialsId);
            if (!selectedCredential) {
                return (0, common_1.stringToToolResult)(`Credential with id "${params.credentialsId}" not found.`, true);
            }
            if (selectedCredential.cloud_only) {
                return (0, common_1.stringToToolResult)(`Cannot use Cloud Credentials [${params.credentialsId}] for test training. Cloud credentials are only available in cloud runs. Please use a non-cloud credential instead.`, true);
            }
        }
        if (!params.credentialsId &&
            nonCloudCredentials.length > 0 &&
            !params.withoutCredentials) {
            const credentialsList = nonCloudCredentials
                .map((cred) => `- ${cred.name} (ID: ${cred.id}, Type: ${cred.type})`)
                .join('\n');
            return (0, common_1.stringToToolResult)(`Would you like to add credentials to this test? Here are the available non-cloud credentials:\n\n${credentialsList}\n\nIf you want to use one of these credentials, please specify the credentialsId parameter with the desired credential ID. If you don't want to use any credentials, you can proceed without specifying credentialsId and set withoutCredentials to true.`, false);
        }
        let fullIntent = params.intent;
        if (params.steps) {
            fullIntent += `\n\nSteps:\n${params.steps}`;
        }
        if (params.intentUrl) {
            fullIntent += `\n\nReference URL: ${params.intentUrl}`;
        }
        if (params.issueOrTicket) {
            fullIntent += `\n\nIssue or ticket: ${params.issueOrTicket}`;
        }
        let planningArtifacts;
        let planningMessages;
        if (params.isApiTest) {
            planningArtifacts = [
                {
                    id: (0, uuid_1.v4)(),
                    artifact_type: 'inline',
                    name: 'test_information',
                    description: 'Test information',
                    artifact_data: {
                        type: 'json',
                        value: {
                            name: params.name,
                            url_override: params.url,
                            application_id: params.applicationId,
                            environment_id: params.environmentId,
                            test_case: fullIntent,
                            test_type: mablApi_1.TestTypeEnum.Api,
                        },
                    },
                },
                {
                    id: (0, uuid_1.v4)(),
                    artifact_type: 'inline',
                    name: 'api_spec',
                    description: 'OpenAPI/Swagger spec or Postman collection for API test generation',
                    artifact_data: {
                        type: 'text',
                        text: params.apiSpec,
                    },
                },
            ];
            planningMessages = [];
        }
        else {
            messaging_1.mablEventEmitter.resetOutputEventChannel();
            const planningSessionResponse = await mablApiClient.generateTestPlan({
                workspaceId,
                messages: [
                    {
                        role: mablApi_1.ChatMessageRoleEnum.User,
                        message: fullIntent,
                        timestamp: Date.now(),
                    },
                ],
                artifact: {
                    version: 0,
                    timestamp: Date.now(),
                },
                generationReferences: {},
                trainingSessionId: `mcp-${Date.now()}`,
            });
            const builtArtifacts = [];
            const testInformation = planningSessionResponse.artifact.test_information;
            if (testInformation) {
                builtArtifacts.push({
                    id: (0, uuid_1.v4)(),
                    description: 'Test information',
                    artifact_type: 'inline',
                    name: 'test_information',
                    artifact_data: {
                        type: 'json',
                        value: testInformation,
                    },
                });
            }
            const testOutline = planningSessionResponse.artifact.agent_state?.entireTestPlan;
            if (testOutline) {
                builtArtifacts.push({
                    id: (0, uuid_1.v4)(),
                    description: 'Test outline',
                    artifact_type: 'inline',
                    name: 'test_outline',
                    artifact_data: {
                        type: 'json',
                        value: testOutline,
                    },
                });
            }
            planningArtifacts = builtArtifacts;
            planningMessages = planningSessionResponse.messages;
        }
        const initiateRequest = {
            is_cloud: false,
            planning_artifacts: planningArtifacts,
            planning_messages: planningMessages,
            application_id: params.applicationId,
            environment_id: params.environmentId,
        };
        const initiateResponse = await mablApiClient.initiateTestAuthoringSession(workspaceId, initiateRequest);
        const agentSessionId = initiateResponse.session_id;
        const trainerUrl = await (0, trainingSessions_1.trainNewTest)({
            environmentId: params.environmentId,
            applicationId: params.applicationId,
            credentialsId: params.credentialsId,
            url: params.url,
            testName: params.name ?? 'New Test',
            autoBranch: false,
            autoLogin: false,
            workspaceId,
            intent: fullIntent,
            testType: params.isApiTest ? mablApi_1.TestTypeEnum.Api : mablApi_1.TestTypeEnum.Browser,
            agentSessionId,
            initialArtifacts: params.isApiTest ? undefined : planningArtifacts,
        }, mablApiClient, false);
        return {
            content: [
                {
                    type: 'text',
                    text: (0, testUtils_1.getCreateTestOutputText)(trainerUrl),
                },
            ],
        };
    },
});
exports.default = [createMablTest];
