"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mcpMablTool_1 = require("./mcpMablTool");
const zod_1 = require("zod");
const common_1 = require("../utils/common");
const featureSet_1 = require("@mablhq-internal/runtime/api/featureSet");
const runCloudTestGeneration_1 = require("@mablhq-internal/runtime/trainer/cli/runCloudTestGeneration");
const mablApi_1 = require("@mablhq-internal/runtime/mablApi");
const testUtils_1 = require("../utils/testUtils");
const baseFields = {
    applicationId: zod_1.z
        .string()
        .describe('The id of the application to create the test in'),
    environmentId: zod_1.z
        .string()
        .describe('The id of the environment to create 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.
          `),
    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.
          `),
    steps: zod_1.z
        .string()
        .describe(`Optional list of steps to accomplish the intent. Put each step on a new line.
          If you are testing an API, include data to be sent in the request and the expected response.
          `)
        .optional(),
    credentialsId: zod_1.z
        .string()
        .describe('Optional id of the credentials to use during test generation. When omitted, the planner picks the application default.')
        .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 outputSchema = zod_1.z.object({
    testType: zod_1.z
        .enum(['browser', 'api'])
        .describe('Discriminator: "browser" for cloud agentic test generation (poll with #get_cloud_test_gen_status); "api" for synchronously-created API tests.'),
    sessionId: zod_1.z
        .string()
        .describe('Browser tests: the agent session ID for the cloud test generation.')
        .optional(),
    instanceId: zod_1.z
        .string()
        .describe('Browser tests: the cloud instance ID for the cloud test generation.')
        .optional(),
    testId: zod_1.z
        .string()
        .describe('API tests: the id of the created API test.')
        .optional(),
    testName: zod_1.z
        .string()
        .describe('API tests: the name of the created API test.')
        .optional(),
    viewTaskUrl: zod_1.z
        .string()
        .describe('API tests: URL to view the created test in the mabl web app.')
        .optional(),
});
const createMablTestCloud = (0, mcpMablTool_1.defineTool)({
    schema: {
        name: 'create_mabl_test_cloud',
        title: 'Create a mabl test in the cloud',
        description: 'Create a new browser or API test that runs in the mabl cloud, without needing a local browser. ' +
            'Use isApiTest=false to create a browser test; the response includes session and instance IDs ' +
            'that can be polled with #get_cloud_test_gen_status. 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; the response returns the created test id and name ' +
            '(no polling required).',
        inputSchema,
        type: 'destructive',
        outputSchema,
    },
    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);
        }
        let fullIntent = params.intent;
        if (params.steps) {
            fullIntent += `\n\nSteps:\n${params.steps}`;
        }
        if (params.isApiTest) {
            const stepResponse = await mablApiClient.generateSteps(workspaceId, fullIntent, {
                applicationId: params.applicationId,
                environmentId: params.environmentId,
                url: params.url,
                api_description: params.apiSpec,
                testType: mablApi_1.TestTypeEnum.Api,
            });
            const apiTestSteps = flattenApiTestSteps(stepResponse.steps);
            if (apiTestSteps.length === 0) {
                return (0, common_1.stringToToolResult)('API test generation returned no steps. Try providing a more detailed intent or API spec.', true);
            }
            const flow = await mablApiClient.createFlow({
                organization_id: workspaceId,
                workspace_id: workspaceId,
                flow_type: mablApi_1.FlowTypeEnum.Api,
                description: params.name,
                reusable: false,
                api_steps: {
                    info: {
                        name: params.name,
                        schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json',
                    },
                    item: apiTestSteps,
                    event: [],
                },
            });
            const created = await mablApiClient.createJourney({
                name: params.name,
                organization_id: workspaceId,
                workspace_id: workspaceId,
                application_id: params.applicationId,
                environment_id: params.environmentId,
                url: params.url,
                api_url: params.url,
                test_type: mablApi_1.TestTypeEnum.Api,
                flows: flow.id ? [flow.id] : [],
            });
            const testId = created.id ?? '';
            const testName = created.name ?? params.name;
            const viewTaskUrl = created.invariant_id !== undefined
                ? (0, testUtils_1.getViewTestUrl)(workspaceId, created.invariant_id)
                : undefined;
            return {
                content: [
                    {
                        type: 'text',
                        text: `API test "${testName}" created (id: ${testId}).` +
                            (viewTaskUrl ? `\nView test: ${viewTaskUrl}` : ''),
                    },
                ],
                structuredContent: {
                    testType: 'api',
                    testId,
                    testName,
                    ...(viewTaskUrl ? { viewTaskUrl } : {}),
                },
            };
        }
        const result = await (0, runCloudTestGeneration_1.runCloudTestGeneration)({
            url: params.url,
            testName: params.name,
            workspaceId,
            environmentId: params.environmentId,
            applicationId: params.applicationId,
            credentialsId: params.credentialsId,
            testIntent: fullIntent,
        }, mablApiClient);
        return {
            content: [
                {
                    type: 'text',
                    text: `Cloud test generation initiated successfully.\n\nSession ID: ${result.sessionId}\nInstance ID: ${result.instanceId ?? 'pending'}\n\nUse #get_cloud_test_gen_status to check the status of the test generation.`,
                },
            ],
            structuredContent: {
                testType: 'browser',
                sessionId: result.sessionId,
                instanceId: result.instanceId,
            },
        };
    },
});
function flattenApiTestSteps(steps) {
    if (!steps) {
        return [];
    }
    const result = [];
    for (const step of steps) {
        if (step.stepType === mablApi_1.Step.StepTypeEnum.StepGroup) {
            const stepGroup = step;
            if (stepGroup.steps) {
                for (const inner of stepGroup.steps) {
                    if (inner.stepType === mablApi_1.Step.StepTypeEnum.ApiTestStep) {
                        result.push(inner);
                    }
                }
            }
        }
        else if (step.stepType === mablApi_1.Step.StepTypeEnum.ApiTestStep) {
            result.push(step);
        }
    }
    return result;
}
exports.default = [createMablTestCloud];
