"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.CliTestGenerationState = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const mablscript_step_types_1 = require("../sharedUtils/mablscript-step-types");
const mablscriptFind_1 = require("@mablhq/test-model/mablscriptFind");
const stepIndexUtils_1 = require("../sharedUtils/stepIndexUtils");
const stepSerialization_1 = require("../sharedUtils/mablscript/stepSerialization");
const variable_utils_1 = require("../sharedUtils/variable-utils");
class CliTestGenerationState {
    constructor(options) {
        this.status = 'not_started';
        this.conversations = [];
        this.steps = [];
        this.nextStepIndex = [0];
        this.variables = {};
        this.snippetsByInvariantId = {};
        this.replayRunning = false;
        this.replayResponse = {
            status: mablscript_step_types_1.StepStatus.Passed,
            message: '',
        };
        this.capturingHovers = false;
        this.authoringMessages = [];
        this.artifacts = new Map();
        this.lastSentMessageCount = 0;
        this.testIntent = options.testIntent;
        this.lastVisitUrl = options.url;
        this.workspaceId = options.workspaceId;
        this.applicationId = options.applicationId;
        this.trainingAction = options.isEditSession ? 'edit' : 'new';
        this.trainingSessionId = `cli-${Date.now()}`;
        this.testVariantId = options.testVariantId;
        this.elementSelectors = new mablscriptFind_1.ElementSelectorStore();
    }
    getStatus() {
        return this.status;
    }
    setStatus(status) {
        this.status = status;
    }
    getActiveSession() {
        return this.activeSession;
    }
    setActiveSession(session) {
        this.activeSession = session;
    }
    getAgentState() {
        return this.agentState;
    }
    setAgentState(state) {
        this.agentState = state;
    }
    getPublicState() {
        return this.publicState;
    }
    setPublicState(state) {
        this.publicState = state;
    }
    getTestIntent() {
        return this.testIntent;
    }
    getConversations() {
        return this.conversations;
    }
    addConversation(conversation) {
        this.conversations.push(conversation);
    }
    getLastToolsExecuted() {
        return this.lastToolsExecuted;
    }
    setLastToolsExecuted(tools) {
        this.lastToolsExecuted = tools;
    }
    getSteps() {
        return this.steps;
    }
    addStep(step) {
        this.steps.push(step);
        this.nextStepIndex = [this.steps.length];
    }
    addSteps(steps) {
        this.steps.push(...steps);
        this.nextStepIndex = [this.steps.length];
    }
    insertStepsAtCursor(steps) {
        const cursorIndex = this.nextStepIndex.length === 1
            ? this.nextStepIndex[0]
            : this.steps.length;
        this.steps.splice(cursorIndex, 0, ...steps);
        this.nextStepIndex = [cursorIndex + steps.length];
    }
    deleteLastSteps(count) {
        const stepsAtLevel = (0, stepIndexUtils_1.getStepsAtCurrentLevel)(this.steps, this.nextStepIndex);
        const cursorPositionInLevel = this.nextStepIndex[this.nextStepIndex.length - 1];
        const actualCount = Math.min(count, cursorPositionInLevel);
        if (actualCount > 0) {
            stepsAtLevel.splice(cursorPositionInLevel - actualCount, actualCount);
            const newIndex = [...this.nextStepIndex];
            newIndex[newIndex.length - 1] = cursorPositionInLevel - actualCount;
            this.nextStepIndex = newIndex;
        }
        return actualCount;
    }
    deleteStepAtPath(path) {
        const getNestedSteps = (step) => {
            if ((0, mablscript_step_types_1.isStepGroupStep)(step) && step.stepsInGroup) {
                return step.stepsInGroup;
            }
            return undefined;
        };
        const parentPath = path.slice(0, -1);
        const indexInParent = path[path.length - 1];
        let parentSteps;
        if (parentPath.length === 0) {
            parentSteps = this.steps;
        }
        else {
            const parentStep = (0, stepIndexUtils_1.getStepAtPath)(this.steps, parentPath, getNestedSteps);
            if (parentStep &&
                (0, mablscript_step_types_1.isStepGroupStep)(parentStep) &&
                parentStep.stepsInGroup) {
                parentSteps = parentStep.stepsInGroup;
            }
            else {
                return `Cannot resolve parent container at position ${(0, stepIndexUtils_1.pathToStepIndex)(parentPath)}`;
            }
        }
        const positionLabel = (0, stepIndexUtils_1.pathToStepIndex)(path);
        if (indexInParent < 0 || indexInParent >= parentSteps.length) {
            const parentLabel = parentPath.length === 0 ? 'root' : (0, stepIndexUtils_1.pathToStepIndex)(parentPath);
            return `No step at position ${positionLabel}: ${parentLabel} has ${parentSteps.length} step(s) (valid range: 1-${parentSteps.length})`;
        }
        parentSteps.splice(indexInParent, 1);
        this.nextStepIndex =
            indexInParent >= parentSteps.length
                ? [...parentPath, parentSteps.length]
                : [...parentPath, indexInParent];
        return undefined;
    }
    deleteStepsInRange(startPath, endPath) {
        const getNestedSteps = (step) => {
            if ((0, mablscript_step_types_1.isStepGroupStep)(step) && step.stepsInGroup) {
                return step.stepsInGroup;
            }
            return undefined;
        };
        const startParent = startPath.slice(0, -1);
        const endParent = endPath.slice(0, -1);
        if (startParent.length !== endParent.length ||
            !startParent.every((v, i) => v === endParent[i])) {
            return `Cannot delete range across different parents: ${(0, stepIndexUtils_1.pathToStepIndex)(startPath)} and ${(0, stepIndexUtils_1.pathToStepIndex)(endPath)} are not siblings`;
        }
        const startIdx = startPath[startPath.length - 1];
        const endIdx = endPath[endPath.length - 1];
        if (startIdx > endIdx) {
            return `Invalid range: start position ${(0, stepIndexUtils_1.pathToStepIndex)(startPath)} is after end position ${(0, stepIndexUtils_1.pathToStepIndex)(endPath)}`;
        }
        const parentPath = startParent;
        let parentSteps;
        if (parentPath.length === 0) {
            parentSteps = this.steps;
        }
        else {
            const parentStep = (0, stepIndexUtils_1.getStepAtPath)(this.steps, parentPath, getNestedSteps);
            if (parentStep &&
                (0, mablscript_step_types_1.isStepGroupStep)(parentStep) &&
                parentStep.stepsInGroup) {
                parentSteps = parentStep.stepsInGroup;
            }
            else {
                return `Cannot resolve parent container at position ${(0, stepIndexUtils_1.pathToStepIndex)(parentPath)}`;
            }
        }
        if (startIdx < 0 || endIdx >= parentSteps.length) {
            const parentLabel = parentPath.length === 0 ? 'root' : (0, stepIndexUtils_1.pathToStepIndex)(parentPath);
            return `Range out of bounds: ${parentLabel} has ${parentSteps.length} step(s) (valid range: 1-${parentSteps.length})`;
        }
        const deleteCount = endIdx - startIdx + 1;
        parentSteps.splice(startIdx, deleteCount);
        this.nextStepIndex =
            startIdx >= parentSteps.length
                ? [...parentPath, parentSteps.length]
                : [...parentPath, startIdx];
        return undefined;
    }
    getNextStepIndex() {
        return this.nextStepIndex;
    }
    setNextStepIndex(index) {
        this.nextStepIndex = index;
    }
    getLastVisitUrl() {
        return this.lastVisitUrl;
    }
    setLastVisitUrl(url) {
        this.lastVisitUrl = url;
    }
    moveCursorIntoGroup() {
        const lastIndex = this.nextStepIndex[this.nextStepIndex.length - 1];
        if (lastIndex > 0) {
            this.nextStepIndex = [
                ...this.nextStepIndex.slice(0, -1),
                lastIndex - 1,
                0,
            ];
        }
        else {
            this.nextStepIndex = [...this.nextStepIndex, 0];
        }
    }
    moveCursorOutOfGroup() {
        if (this.nextStepIndex.length > 1) {
            const parentPath = this.nextStepIndex.slice(0, -1);
            this.nextStepIndex = [
                ...parentPath.slice(0, -1),
                parentPath[parentPath.length - 1] + 1,
            ];
        }
    }
    isInsideStepGroup() {
        return this.nextStepIndex.length > 1;
    }
    getVariables() {
        return this.variables;
    }
    setVariable(name, variable) {
        this.variables[name] = variable;
    }
    replaceVariables(namespace) {
        this.variables = namespace;
    }
    getSnippetsByInvariantId() {
        return this.snippetsByInvariantId;
    }
    setSnippet(invariantId, snippet) {
        this.snippetsByInvariantId[invariantId] = snippet;
    }
    isReplayRunning() {
        return this.replayRunning;
    }
    setReplayRunning(running) {
        this.replayRunning = running;
    }
    getReplayResponse() {
        return this.replayResponse;
    }
    setReplayResponse(response) {
        this.replayResponse = response;
    }
    getLastFlowFailure() {
        return this.lastFlowFailure;
    }
    setLastFlowFailure(failure) {
        this.lastFlowFailure = failure;
    }
    getTrainingAction() {
        return this.trainingAction;
    }
    getTrainingSessionId() {
        return this.trainingSessionId;
    }
    getWorkspaceId() {
        return this.workspaceId;
    }
    getApplicationId() {
        return this.applicationId;
    }
    getTestVariantId() {
        return this.testVariantId;
    }
    getElementSelectors() {
        return this.elementSelectors;
    }
    isCapturingHovers() {
        return this.capturingHovers;
    }
    setCapturingHovers(capturing) {
        this.capturingHovers = capturing;
    }
    getAuthoringSessionId() {
        return this.authoringSessionId;
    }
    setAuthoringSessionId(sessionId) {
        this.authoringSessionId = sessionId;
    }
    getAuthoringMessages() {
        return this.authoringMessages;
    }
    addAuthoringMessages(messages) {
        this.authoringMessages = [...this.authoringMessages, ...messages];
    }
    clearAuthoringMessages() {
        this.authoringMessages = [];
        this.lastSentMessageCount = 0;
    }
    getLastSentMessageCount() {
        return this.lastSentMessageCount;
    }
    setLastSentMessageCount(count) {
        this.lastSentMessageCount = count;
    }
    getArtifacts() {
        return this.artifacts;
    }
    setArtifact(name, artifact) {
        this.artifacts.set(name, artifact);
    }
    getArtifact(name) {
        return this.artifacts.get(name);
    }
    clearArtifacts() {
        this.artifacts.clear();
    }
    async save(filePath) {
        await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
        await fs.promises.writeFile(filePath, JSON.stringify(this.serialize(), undefined, 2), 'utf8');
    }
    static async load(filePath) {
        const serializedJson = await fs.promises.readFile(filePath, 'utf8');
        const serialized = JSON.parse(serializedJson);
        return CliTestGenerationState.deserialize(serialized);
    }
    serialize() {
        const variables = this.variables;
        const aliasedVariables = (0, variable_utils_1.aliasVariables)(variables);
        return {
            version: 1,
            testIntent: this.testIntent,
            url: this.lastVisitUrl,
            workspaceId: this.workspaceId,
            applicationId: this.applicationId,
            isEditSession: this.trainingAction === 'edit',
            testVariantId: this.testVariantId,
            steps: this.steps.map((step) => (0, stepSerialization_1.parseStepToV2Format)(step, false, variables, aliasedVariables)),
            nextStepIndex: this.nextStepIndex,
            lastVisitUrl: this.lastVisitUrl,
            variables: this.variables,
            snippetsByInvariantId: this.snippetsByInvariantId,
            authoringSessionId: this.authoringSessionId,
            authoringMessages: this.authoringMessages.length > 0 ? this.authoringMessages : undefined,
            lastSentMessageCount: this.lastSentMessageCount > 0 ? this.lastSentMessageCount : undefined,
        };
    }
    static deserialize(serialized) {
        if (serialized.version !== 1) {
            throw new Error(`Unsupported CliTestGenerationState serialization version: ${serialized.version}`);
        }
        const state = new CliTestGenerationState({
            testIntent: serialized.testIntent,
            url: serialized.url,
            workspaceId: serialized.workspaceId,
            applicationId: serialized.applicationId,
            isEditSession: serialized.isEditSession,
            testVariantId: serialized.testVariantId,
        });
        const variables = serialized.variables ?? {};
        const snippets = serialized.snippetsByInvariantId ?? {};
        state.variables = variables;
        state.snippetsByInvariantId = snippets;
        const persistedVariables = {};
        for (const [name, entry] of Object.entries(variables)) {
            persistedVariables[name] = entry;
        }
        state.steps = serialized.steps.map((formattedStep) => (0, stepSerialization_1.parseFormattedStepToBaseStep)(formattedStep, variables, false, snippets));
        Object.assign(variables, persistedVariables);
        state.nextStepIndex = serialized.nextStepIndex;
        state.lastVisitUrl = serialized.lastVisitUrl;
        if (serialized.authoringSessionId !== undefined) {
            state.authoringSessionId = serialized.authoringSessionId;
        }
        if (serialized.authoringMessages !== undefined) {
            state.authoringMessages = serialized.authoringMessages;
        }
        if (serialized.lastSentMessageCount !== undefined) {
            state.lastSentMessageCount = serialized.lastSentMessageCount;
        }
        return state;
    }
}
exports.CliTestGenerationState = CliTestGenerationState;
