"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;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.launchTrainingSession = launchTrainingSession;
const env_1 = require("@mablhq-internal/runtime/env/env");
const util_1 = require("../../commandUtil/util");
const cliUtil_1 = require("@mablhq-internal/runtime/core/cliUtil");
const constants_1 = require("@mablhq-internal/runtime/core/constants");
const constants_2 = require("../../constants");
const trainingSessions_1 = require("@mablhq-internal/runtime/core/trainer/trainingSessions");
const runAgenticGeneration_1 = require("@mablhq-internal/runtime/trainer/cli/runAgenticGeneration");
const mablApiClientFactory_1 = require("@mablhq-internal/runtime/api/mablApiClientFactory");
const pureUtil_1 = require("@mablhq-internal/runtime/util/pureUtil");
const saveGeneratedTest_1 = require("@mablhq-internal/runtime/trainer/generation/saveGeneratedTest");
const ViewportStep_1 = __importStar(require("@mablhq-internal/runtime/trainer/sharedUtils/mablscript/canonical/ViewportStep"));
const VisitUrlStep_1 = __importStar(require("@mablhq-internal/runtime/trainer/sharedUtils/mablscript/canonical/VisitUrlStep"));
const inquirer = __importStar(require("inquirer"));
const runCloudTestGeneration_1 = require("@mablhq-internal/runtime/trainer/cli/runCloudTestGeneration");
const chalk = require('chalk');
const CommandArgAutoSave = 'save';
const CommandArgMode = 'mode';
const CommandArgDisabled = 'disabled';
const CommandArgEmpty = 'empty';
const CommandArgSnapshot = 'snapshot';
var PostGenerationActions;
(function (PostGenerationActions) {
    PostGenerationActions["Save"] = "Save the test";
    PostGenerationActions["Discard"] = "Discard without saving";
})(PostGenerationActions || (PostGenerationActions = {}));
exports.command = `create <${constants_1.CommandArgUrl}> <${constants_2.CommandArgTestName}>`;
exports.describe = 'Create a browser test using the mabl Trainer';
exports.builder = (yargs) => {
    yargs
        .positional(constants_1.CommandArgUrl, {
        describe: 'The url to test',
        type: 'string',
    })
        .positional(constants_2.CommandArgTestName, {
        describe: 'The name of the test',
        type: 'string',
    })
        .option('desc', {
        alias: constants_2.CommandArgTestDescription,
        describe: 'Description for the test',
        default: '',
        nargs: 1,
        type: 'string',
    })
        .option(constants_2.CommandArgWidth, {
        describe: 'Set the browser width in pixels',
        default: constants_2.DEFAULT_BROWSER_WIDTH,
        nargs: 1,
        type: 'number',
    })
        .option(constants_2.CommandArgHeight, {
        describe: 'Set the browser height in pixels',
        default: constants_2.DEFAULT_BROWSER_HEIGHT,
        nargs: 1,
        type: 'number',
    })
        .option(constants_1.CommandArgMablBranch, {
        describe: 'Branch to run the mabl test against',
        nargs: 1,
        type: 'string',
    })
        .option(constants_1.CommandArgEnvironmentId, {
        alias: constants_2.CommandArgAliases.EnvironmentId,
        describe: 'Mabl environment to create test under',
        nargs: 1,
        type: 'string',
    })
        .option(constants_1.CommandArgApplicationId, {
        alias: constants_2.CommandArgAliases.ApplicationId,
        describe: 'Mabl application to create test under',
        nargs: 1,
        type: 'string',
    })
        .option(constants_1.CommandArgPlanId, {
        describe: 'Mabl plan to use the config from and add the test to upon completion',
        nargs: 1,
        type: 'string',
    })
        .option(constants_2.CommandArgMablAutoBranch, {
        describe: 'Create a mabl branch when a mabl-branch target is specified that does not exist',
        type: 'boolean',
        default: false,
    })
        .option(constants_2.CommandArgMablAutoLogin, {
        describe: 'Insert an auto login flow at the beginning of the created test',
        type: 'boolean',
        default: false,
    })
        .option(constants_1.CommandArgLabels, {
        describe: 'Space delimited labels to save test with',
        type: 'array',
    })
        .option(constants_2.CommandArgDataTables, {
        describe: 'Space delimited data table IDs to use with test',
        type: 'array',
    })
        .option(constants_1.CommandArgWorkspaceId, {
        alias: constants_2.CommandArgAliases.WorkspaceId,
        describe: 'Workspace to create test in',
        nargs: 1,
        type: 'string',
    })
        .option(constants_1.CommandArgCredentials, {
        alias: constants_2.CommandArgAliases.Credentials,
        describe: 'Credentials ID to run the test with',
        nargs: 1,
        type: 'string',
    })
        .option(constants_2.CommandArgIntent, {
        describe: 'Intent for the test, e.g. "smoke", "regression"',
        nargs: 1,
        type: 'string',
    })
        .option(CommandArgDisabled, {
        describe: 'Create the test in a disabled state',
        type: 'boolean',
        default: false,
    })
        .option(CommandArgEmpty, {
        describe: 'Create a minimal test with only viewport and visit-URL steps',
        type: 'boolean',
        default: false,
    })
        .option(constants_2.CommandArgTestIntent, {
        hidden: true,
        describe: 'The test intent/goal for agentic test generation. When provided, enables agentic mode.',
        nargs: 1,
        type: 'string',
    })
        .option(constants_2.CommandArgHeadless, {
        hidden: true,
        describe: 'Run browser in headless mode during agentic generation',
        type: 'boolean',
        default: false,
    })
        .option(constants_2.CommandArgVerbose, {
        hidden: true,
        describe: 'Enable verbose logging for agentic generation',
        type: 'boolean',
        default: false,
    })
        .option(CommandArgAutoSave, {
        hidden: true,
        describe: 'Automatically save test after agentic generation',
        type: 'boolean',
        default: false,
    })
        .option(constants_2.CommandArgOutputScreenshots, {
        hidden: true,
        describe: 'Output base64-encoded screenshots to stdout during generation',
        type: 'boolean',
        default: false,
    })
        .option(CommandArgMode, {
        describe: 'Test generation mode: "local" runs locally (default), "cloud" runs in the mabl cloud and returns session/instance IDs for polling status.',
        type: 'string',
        choices: ['local', 'cloud'],
        default: 'local',
    });
    if (env_1.ENV !== 'prod') {
        yargs.option(CommandArgSnapshot, {
            hidden: true,
            describe: 'Pin cloud test generation to a specific snapshot image. Pass the 7-char short commit hash of the target build (e.g. --snapshot abc1234).',
            type: 'string',
        });
    }
};
exports.handler = (0, cliUtil_1.failWrapper)(launchTrainingSession);
async function launchTrainingSession(parsed) {
    const url = parsed.url;
    const width = parsed.width;
    const height = parsed.height;
    const testName = parsed['test-name'];
    const workspaceId = await (0, util_1.getWorkspaceId)(parsed);
    const testDescription = parsed['test-description'];
    const branchName = parsed['mabl-branch'];
    const autoBranch = parsed['auto-branch'];
    const autoLogin = parsed[constants_2.CommandArgMablAutoLogin];
    const credentialsId = parsed['credentials-id'];
    const environmentId = parsed[constants_1.CommandArgEnvironmentId];
    const applicationId = parsed[constants_1.CommandArgApplicationId];
    const planId = parsed[constants_1.CommandArgPlanId];
    const labels = parsed[constants_1.CommandArgLabels];
    const dataTableIds = parsed[constants_2.CommandArgDataTables];
    const intent = parsed[constants_2.CommandArgIntent];
    const disabled = parsed[CommandArgDisabled];
    const enabled = disabled ? false : undefined;
    const testIntent = parsed[constants_2.CommandArgTestIntent];
    if (parsed[CommandArgEmpty]) {
        const apiClient = await mablApiClientFactory_1.MablApiClientFactory.createApiClient();
        const viewportStep = new ViewportStep_1.default({ width, height });
        const visitUrlStep = new VisitUrlStep_1.default(url);
        const rawSteps = [viewportStep, visitUrlStep];
        const stepDescriptions = [
            (0, ViewportStep_1.humanizeViewportStep)(viewportStep),
            (0, VisitUrlStep_1.humanizeVisitUrlStep)(visitUrlStep),
        ];
        console.log(chalk.cyan('Creating empty test...'));
        const result = await (0, saveGeneratedTest_1.saveGeneratedTest)({
            apiClient,
            workspaceId,
            applicationId,
            url,
            testName,
            testDescription,
            labels,
            rawSteps,
            stepDescriptions,
            credentialsId,
            enabled,
            testIntent,
        });
        if (result.success) {
            console.log(chalk.green('\nTest saved successfully!'));
            if (result.testId) {
                console.log(chalk.gray('  Test ID:'), chalk.white(result.testId));
            }
            if (result.testUrl) {
                console.log(chalk.gray('  View:'), chalk.cyan(result.testUrl));
            }
        }
        else {
            console.error(chalk.red('Failed to save test:'), result.error);
            throw new Error(result.error);
        }
        return 'done';
    }
    const headless = parsed[constants_2.CommandArgHeadless];
    const verbose = parsed[constants_2.CommandArgVerbose];
    const outputScreenshots = parsed[constants_2.CommandArgOutputScreenshots];
    const mode = parsed[CommandArgMode];
    if (mode === 'cloud') {
        const apiClient = await mablApiClientFactory_1.MablApiClientFactory.createApiClient();
        console.log(chalk.cyan('Initiating cloud test generation...'));
        const result = await (0, runCloudTestGeneration_1.runCloudTestGeneration)({
            url,
            testName,
            workspaceId,
            environmentId,
            applicationId,
            credentialsId,
            testIntent: testIntent ?? intent ?? testName,
            snapshot: parsed[CommandArgSnapshot],
        }, apiClient);
        console.log(chalk.green('\nCloud test generation initiated successfully!'));
        console.log(chalk.gray('  Session ID:'), chalk.white(result.sessionId));
        if (result.instanceId) {
            console.log(chalk.gray('  Instance ID:'), chalk.white(result.instanceId));
        }
        const statusCommand = `mabl tests cloud-status --session-id ${result.sessionId}${result.instanceId ? ` --instance-id ${result.instanceId}` : ''}`;
        console.log(chalk.gray('\n  Check status with:'), chalk.cyan(statusCommand));
        return 'done';
    }
    if (testIntent) {
        const apiClient = await mablApiClientFactory_1.MablApiClientFactory.createApiClient();
        const autoSave = parsed[CommandArgAutoSave];
        const result = await (0, runAgenticGeneration_1.runAgenticGeneration)({
            type: 'new',
            url,
            testIntent,
            workspaceId,
            applicationId,
            headless: headless ?? false,
            verbose: verbose ?? false,
            apiClient,
            appVersion: (0, pureUtil_1.getCliVersion)(),
            autoSave,
            testName,
            testDescription,
            labels,
            outputScreenshots: outputScreenshots ?? false,
        });
        if (result.success) {
            console.log('\nTest generation completed successfully!');
            console.log(`Training Session ID: ${result.trainingSessionId}`);
            console.log(`Steps generated: ${result.steps.length}`);
            if (result.saveResult?.success) {
                console.log(chalk.green('\n✓ Test saved successfully!'));
                console.log(chalk.gray('  Test ID:'), chalk.white(result.saveResult.testId));
                console.log(chalk.gray('  View:'), chalk.cyan(result.saveResult.testUrl));
            }
            else if (result.saveResult?.error) {
                console.error(chalk.red('\n✗ Auto-save failed:'), result.saveResult.error);
                await handlePostGenerationActions({
                    workspaceId,
                    applicationId,
                    url,
                    testName,
                    testIntent,
                    apiClient,
                    result,
                    autoSave: false,
                    enabled,
                });
            }
            else {
                await handlePostGenerationActions({
                    workspaceId,
                    applicationId,
                    url,
                    testName,
                    testIntent,
                    apiClient,
                    result,
                    autoSave: false,
                    enabled,
                });
            }
            return 'done';
        }
        else {
            throw new Error(`Agentic test generation failed: ${result.error}`);
        }
    }
    const trainingSessionOptions = {
        applicationId,
        autoBranch,
        autoLogin,
        branchName,
        credentialsId,
        dataTableIds,
        environmentId,
        height,
        intent,
        labels,
        planId,
        testDescription,
        testName,
        url,
        width,
        workspaceId,
    };
    await (0, trainingSessions_1.trainNewTest)(trainingSessionOptions);
    return 'done';
}
async function handlePostGenerationActions(context) {
    const action = await getNextAction(context.autoSave);
    console.log();
    if (action === PostGenerationActions.Save) {
        await saveTestFromContext(context);
    }
    else {
        console.log(chalk.yellow('Test discarded without saving.'));
    }
}
async function getNextAction(autoSave) {
    if (autoSave) {
        return PostGenerationActions.Save;
    }
    const answer = await inquirer.prompt([
        {
            type: 'list',
            name: 'action',
            message: 'What do you want to do with the generated test?',
            choices: Object.values(PostGenerationActions),
        },
    ]);
    return answer.action;
}
async function saveTestFromContext(context) {
    console.log(chalk.cyan('Saving test...'));
    const result = await (0, saveGeneratedTest_1.saveGeneratedTest)({
        apiClient: context.apiClient,
        workspaceId: context.workspaceId,
        applicationId: context.applicationId,
        url: context.url,
        testName: context.testName,
        testDescription: context.testIntent,
        rawSteps: context.result.rawSteps,
        stepDescriptions: context.result.steps,
        enabled: context.enabled,
        trainingSessionId: context.result.trainingSessionId,
    });
    if (result.success) {
        console.log(chalk.green('✓ Test saved successfully!'));
        if (result.testId) {
            console.log(chalk.gray('  Test ID:'), chalk.white(result.testId));
        }
        if (result.testUrl) {
            console.log(chalk.gray('  View:'), chalk.cyan(result.testUrl));
        }
    }
    else {
        console.error(chalk.red('✗ Failed to save test:'), result.error);
        throw new Error(result.error);
    }
}
