"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.CONDITIONAL_TYPE_ELSEIF = void 0;
exports.humanizeAssertStep = humanizeAssertStep;
exports.isMobileWebViewAssertStep = isMobileWebViewAssertStep;
exports.isMobileFindAssertStep = isMobileFindAssertStep;
exports.isAssertionStatus = isAssertionStatus;
exports.assertStepToAIString = assertStepToAIString;
const StepWithFind_1 = __importStar(require("./StepWithFind"));
const yaml_utils_1 = require("../yaml-utils");
const dom_util_1 = require("@mablhq-internal/mablscript-find/dom-util");
const mablscriptFind_1 = require("@mablhq/test-model/mablscriptFind");
const AssertStepTypes_1 = __importDefault(require("./AssertStepTypes"));
const location_1 = require("../location");
const email_1 = require("../email");
const mablscript_utils_1 = require("../mablscript-utils");
const assertionUtil_1 = require("../assertionUtil");
const common_1 = require("../../common");
const variable_utils_1 = require("../../variable-utils");
const variable_names_util_1 = require("../../variable-names-util");
const type_utils_1 = require("../../type-utils");
const MablAction_1 = require("@mablhq/test-model/MablAction");
const mablscript_step_types_1 = require("../../mablscript-step-types");
Object.defineProperty(exports, "CONDITIONAL_TYPE_ELSEIF", { enumerable: true, get: function () { return mablscript_step_types_1.CONDITIONAL_TYPE_ELSEIF; } });
const AssertStep_1 = require("@mablhq/test-model/steps/AssertStep");
const AssertVariableStep_1 = __importDefault(require("./AssertVariableStep"));
const MablSymbol_1 = require("@mablhq/test-model/MablSymbol");
const ConditionDescriptor_1 = require("@mablhq/test-model/types/ConditionDescriptor");
const BaseStep_1 = require("./BaseStep");
const FindAction_1 = require("@mablhq/test-model/actions/FindAction");
const CountAction_1 = require("@mablhq/test-model/actions/CountAction");
const ExtractDescriptor_1 = require("@mablhq/test-model/types/ExtractDescriptor");
const MobileFindAction_1 = require("@mablhq/test-model/mobile/steps/actions/MobileFindAction");
const ExtractAction_1 = require("@mablhq/test-model/actions/ExtractAction");
const importer_1 = require("@mablhq/test-model/importer");
const GetViewportDescriptor_1 = require("@mablhq/test-model/types/GetViewportDescriptor");
const assert_utils_1 = require("./assert-utils");
const USER_NAMESPACE_REGEXP = /^user\./g;
function assertionConditionFieldToConditionType(field) {
    if (field === ConditionDescriptor_1.AssertionConditionField.Present) {
        return ConditionDescriptor_1.ConditionType.Presence;
    }
    if (field === ConditionDescriptor_1.AssertionConditionField.NotPresent) {
        return ConditionDescriptor_1.ConditionType.Presence;
    }
    if (field === ConditionDescriptor_1.AssertionConditionField.AIPrompt) {
        return ConditionDescriptor_1.ConditionType.AIPrompt;
    }
    return ConditionDescriptor_1.ConditionType.Comparison;
}
class AssertStep extends StepWithFind_1.default {
    static getStepType() {
        return mablscript_step_types_1.StepType.ASSERTION;
    }
    getFailedAssert() {
        return {
            level: 'error',
            message: 'Assertion failed',
            isConditional: this.wrapInConditional,
        };
    }
    constructor(findDescriptor, assertionProps = {}) {
        const { selectionType, assertionType, assertionTarget, caseInsensitive, onFailure, elementScreenshot, elementAttrProp, expectedValue, extractionType, variable, wrapInConditional, wrapInConditionalType, findOptions, aiPrompt, } = assertionProps;
        super(AssertStep.getStepType(), findDescriptor, findOptions);
        this.assertionType =
            assertionType ?? (aiPrompt !== undefined ? 'ai_prompt' : undefined);
        this.assertionTarget = assertionTarget;
        this.caseInsensitive = caseInsensitive;
        this.onFailure = onFailure;
        this.elementScreenshot = !!elementScreenshot;
        this.wrapInConditional = wrapInConditional;
        this.wrapInConditionalType = wrapInConditionalType;
        this.elementAttrProp = elementAttrProp ? elementAttrProp : 'innerText';
        this.expectedValue = (0, assertionUtil_1.parseAssertionExpectedValue)(expectedValue);
        this.extractionType = extractionType ?? ExtractDescriptor_1.ExtractType.EXTRACT_ATTRIBUTE;
        this.mergeOptions({ editable: true });
        if (this.extractionType === ExtractDescriptor_1.ExtractType.EXTRACT_PROMPT && aiPrompt) {
            this.aiPrompt = {
                metaPrompt: aiPrompt.metaPrompt
                    ? (0, mablscript_utils_1.repairOverEscapedMablscriptString)(aiPrompt.metaPrompt)
                    : aiPrompt.metaPrompt,
                userPrompt: aiPrompt.userPrompt
                    ? (0, mablscript_utils_1.repairOverEscapedMablscriptString)(aiPrompt.userPrompt)
                    : aiPrompt.userPrompt,
                criteria: aiPrompt.criteria?.map(mablscript_utils_1.repairOverEscapedMablscriptString),
            };
        }
        switch (selectionType) {
            case 'cookie': {
                this.mergeOptions({ executionContext: 'background' });
                break;
            }
            case 'email': {
                this.mergeOptions({ feature: StepWithFind_1.MAILBOX_FEATURE });
                break;
            }
        }
        this.selectionType = selectionType;
        this.variable = variable;
        this.getTargetObjectAttributeValue =
            this.getTargetObjectAttributeValue.bind(this);
    }
    setAsConditional() {
        this.wrapInConditional = true;
    }
    generateMablscript() {
        let extractAttr;
        if (this.selectionType === 'email') {
            extractAttr = `extract_email_attribute("${this.elementAttrProp}")`;
        }
        else if (this.elementAttrProp === 'count') {
            extractAttr = 'count()';
        }
        else if (this.extractionType === ExtractDescriptor_1.ExtractType.EXTRACT_CSS_PROPERTIES) {
            extractAttr = `extract_attribute("${this.elementAttrProp}", {extraction_type: "css"})`;
        }
        else if (this.extractionType === ExtractDescriptor_1.ExtractType.EXTRACT_PROMPT) {
            extractAttr = '';
        }
        else {
            extractAttr = `extract_attribute("${this.elementAttrProp}")`;
        }
        let evaluateArguments = this.generateEvaluateArguments();
        const assertionOptions = this.generateAssertionOptionsArgument();
        const assertionTypeMablscript = (0, assertionUtil_1.getAssertionMablscriptText)(this.assertionType);
        const conditionOptions = this.generateConditionOptionsArgument();
        let extractAndEvaluateConditionAction;
        if (this.extractionType === ExtractDescriptor_1.ExtractType.EXTRACT_PROMPT) {
            const userPromptCleaned = (0, mablscriptFind_1.escapeMablscriptString)((0, mablscript_utils_1.repairOverEscapedMablscriptString)(this.aiPrompt?.userPrompt ?? ''));
            const aiOptions = {};
            if (this.aiPrompt?.metaPrompt) {
                aiOptions.metaPrompt = (0, mablscript_utils_1.repairOverEscapedMablscriptString)(this.aiPrompt.metaPrompt);
            }
            if (this.aiPrompt?.criteria && this.aiPrompt.criteria.length > 0) {
                aiOptions.criteria = this.aiPrompt.criteria.map(mablscript_utils_1.repairOverEscapedMablscriptString);
            }
            extractAndEvaluateConditionAction = `evaluate_ai_prompt("${userPromptCleaned}",${(0, mablscriptFind_1.buildStepArgumentString)({ params: aiOptions, legacy: false })})`;
        }
        else {
            switch (this.assertionType) {
                case AssertStepTypes_1.default.PRESENT:
                    extractAndEvaluateConditionAction = `evaluate_presence("present"${evaluateArguments})`;
                    break;
                case AssertStepTypes_1.default.NOT_PRESENT:
                    extractAndEvaluateConditionAction = `evaluate_presence("not_present"${evaluateArguments})`;
                    break;
                default:
                    if (!evaluateArguments) {
                        console.error('Attempt to save mablscript of evaluate_condition without argument');
                        evaluateArguments = `, ""`;
                    }
                    extractAndEvaluateConditionAction = `${extractAttr}.evaluate_condition("${assertionTypeMablscript}"${evaluateArguments}${conditionOptions})`;
                    break;
            }
        }
        const findAction = this.findDescriptorToMablscript();
        if (this.wrapInConditional) {
            return this.wrapInConditionalType === mablscript_step_types_1.CONDITIONAL_TYPE_ELSEIF
                ? [
                    'conditional_else()',
                    findAction,
                    extractAndEvaluateConditionAction,
                    'conditional_else_if()',
                ]
                    .filter(Boolean)
                    .join('.')
                : [findAction, extractAndEvaluateConditionAction, 'conditional_if()']
                    .filter(Boolean)
                    .join('.');
        }
        const assertionString = `assert(${assertionOptions ? assertionOptions : ''})`;
        const mablscript = [
            findAction,
            extractAndEvaluateConditionAction,
            assertionString,
        ]
            .filter(Boolean)
            .join('.');
        return mablscript;
    }
    generateEvaluateArguments() {
        let expectedValue = this.generateExpectedValueArgument();
        if (expectedValue) {
            expectedValue = `, ${expectedValue}`;
        }
        else {
            expectedValue = '';
        }
        return expectedValue;
    }
    generateExpectedValueArgument() {
        if (this.assertionType === AssertStepTypes_1.default.PRESENT ||
            this.assertionType === AssertStepTypes_1.default.NOT_PRESENT) {
            return;
        }
        switch (this.assertionTarget) {
            case 'variable':
                return this.variable?.name;
            case 'element':
            default:
                return `"${(0, mablscriptFind_1.escapeMablscriptString)((0, dom_util_1.normalizeText)(this.expectedValue))}"`;
        }
    }
    generateAssertionOptionsArgument() {
        const shouldStoreOnFailureValue = this.onFailure && this.onFailure !== AssertStep_1.OnFailure.FailImmediately;
        if (shouldStoreOnFailureValue || this.elementScreenshot) {
            const optionsArray = [];
            if (shouldStoreOnFailureValue) {
                optionsArray.push(`onFailure: "${this.onFailure}"`);
            }
            if (this.elementScreenshot) {
                optionsArray.push(`observationScope: "${AssertStep_1.ObservationScope.Element}"`);
            }
            return `{${optionsArray.join(', ')}}`;
        }
        return '';
    }
    generateConditionOptionsArgument() {
        if (!this.caseInsensitive) {
            return '';
        }
        return `, ${(0, MablAction_1.convertObjectToMablscriptArgs)({
            caseInsensitive: this.caseInsensitive,
        })}`;
    }
    generateMobileCliStep() {
        if (!this.assertionType) {
            throw new Error('Missing assertion type. Unable to generate AssertStep.');
        }
        if (this.wrapInConditionalType) {
            let conditionalTarget;
            if ((0, mablscriptFind_1.isMobileFindSpecification)(this.findDescriptor)) {
                conditionalTarget = {
                    findType: mablscriptFind_1.FindType.FIND_ONE,
                    findTarget: this.findDescriptor,
                    findOptions: this.findOptions,
                };
            }
            else if ((0, mablscriptFind_1.isWebViewFindElementDescriptor)(this.findDescriptor)) {
                conditionalTarget = this.findDescriptor;
            }
            else if ((0, mablscriptFind_1.isViewportFindDescriptor)(this.findDescriptor)) {
                conditionalTarget = (0, GetViewportDescriptor_1.newGetViewportDescriptor)();
            }
            else {
                return this.generateMablStep();
            }
            const condition = assertionConditionFieldToConditionType(this.assertionType);
            const isPresenceAssertion = this.assertionType === ConditionDescriptor_1.AssertionConditionField.Present ||
                this.assertionType === ConditionDescriptor_1.AssertionConditionField.NotPresent;
            const conditionalIfJson = {
                target: conditionalTarget,
                extract: isPresenceAssertion
                    ? undefined
                    : {
                        extractType: this.extractionType,
                        attributeName: this.elementAttrProp,
                    },
                attribute: isPresenceAssertion ? undefined : this.elementAttrProp,
                condition: {
                    conditionType: condition,
                    comparatorValue: this.expectedValue,
                    comparisonType: this.assertionType,
                    presenceType: this.assertionType,
                    caseInsensitive: this.caseInsensitive,
                    ...this.aiPrompt,
                },
                disabled: this.disabled,
                ...(this.elementScreenshot
                    ? { observationScope: AssertStep_1.ObservationScope.Element }
                    : {}),
            };
            const yamlStepName = this.wrapInConditionalType === mablscript_step_types_1.CONDITIONAL_TYPE_ELSEIF
                ? 'ElseIf'
                : 'If';
            const stepYaml = { [yamlStepName]: conditionalIfJson };
            const mablStep = (0, importer_1.interpretStepsFromObjects)([stepYaml], true)[0];
            return mablStep;
        }
        let target;
        if ((0, mablscriptFind_1.isMobileFindSpecification)(this.findDescriptor)) {
            target = {
                findType: mablscriptFind_1.FindType.FIND_ONE,
                findTarget: this.findDescriptor,
                findOptions: this.findOptions,
            };
        }
        else if ((0, mablscriptFind_1.isWebViewFindElementDescriptor)(this.findDescriptor)) {
            target = this.findDescriptor;
        }
        else if ((0, mablscriptFind_1.isViewportFindDescriptor)(this.findDescriptor)) {
            target = (0, GetViewportDescriptor_1.newGetViewportDescriptor)();
        }
        else {
            return this.generateMablStep();
        }
        const assertArguments = {};
        const shouldStoreOnFailureValue = this.onFailure && this.onFailure !== AssertStep_1.OnFailure.FailImmediately;
        if (shouldStoreOnFailureValue || this.elementScreenshot) {
            if (shouldStoreOnFailureValue) {
                assertArguments.onFailure = this.onFailure;
            }
            if (this.elementScreenshot) {
                assertArguments.observationScope = AssertStep_1.ObservationScope.Element;
            }
        }
        const assertStepJson = {
            assertArguments,
            assertionValue: this.expectedValue,
            attribute: this.elementAttrProp,
            conditionOptions: { caseInsensitive: this.caseInsensitive },
            disabled: this.disabled,
            extractType: ExtractAction_1.ExtractAction.mablscriptToYamlType[this.extractionType],
            target,
            aiPrompt: this.aiPrompt,
        };
        if (this.assertionTarget === 'variable') {
            assertStepJson.assertionValue = `{{@${this.variable?.name}}}`;
        }
        const yamlStepName = ConditionDescriptor_1.AssertionConditionFieldToStepName[this.assertionType];
        const stepYaml = { [yamlStepName]: assertStepJson };
        const mablStep = (0, importer_1.interpretStepsFromObjects)([stepYaml], true)[0];
        return mablStep;
    }
    generateMablStep() {
        const mablStep = super.generateMablStep();
        if (this.wrapInConditional && this.elementScreenshot) {
            if ((0, assert_utils_1.isIfConditionStep)(mablStep) || (0, assert_utils_1.isElseIfConditionStep)(mablStep)) {
                mablStep.descriptor.observationScope = AssertStep_1.ObservationScope.Element;
                mablStep.observationScope = AssertStep_1.ObservationScope.Element;
            }
        }
        return mablStep;
    }
    getExpectedValue(variables, shouldTruncate) {
        try {
            const value = this.assertionTextForComparison(variables);
            if (typeof value === 'string') {
                return (0, dom_util_1.normalizeText)(value, shouldTruncate);
            }
            return (0, dom_util_1.normalizeText)(JSON.stringify(value), shouldTruncate);
        }
        catch (e) {
            return {
                level: 'error',
                message: e instanceof Error
                    ? e.message.startsWith('Cannot resolve variable')
                        ? e.message
                        : 'Assertion failed'
                    : 'unknown getExpectedValue error',
                isConditional: this.wrapInConditional,
            };
        }
    }
    inputVariables() {
        const findInputs = super.inputVariables();
        const variableValueInputs = this.variable?.name ? [this.variable.name] : [];
        const expectedValueInputs = this.expectedValue
            ? (0, variable_names_util_1.extractVariableNamesFromPattern)(this.expectedValue)
            : [];
        return (0, type_utils_1.distinct)([
            ...findInputs,
            ...variableValueInputs,
            ...expectedValueInputs,
        ]);
    }
    getTargetObjectAttributeValue(targetObject) {
        let effectiveObject = targetObject;
        if (this.selectionType === 'location') {
            effectiveObject = (0, location_1.normalizeLocationAttributes)(targetObject);
        }
        else if (this.selectionType === 'email') {
            effectiveObject = (0, email_1.normalizeEmailAttributes)(targetObject);
        }
        const result = effectiveObject[this.elementAttrProp];
        if (!result) {
            return effectiveObject.getAttribute(this.elementAttrProp);
        }
        return result;
    }
    assertionTextForComparison(variables) {
        switch (this.assertionTarget) {
            case 'variable':
                if (this.variable?.name) {
                    return variables[this.variable?.name].value;
                }
                return (0, variable_utils_1.safelyGeneratePatternPreview)(this.expectedValue, variables, defaultComparisonErrorFunc);
            case 'element':
                return (0, variable_utils_1.safelyGeneratePatternPreview)(this.expectedValue, variables, defaultComparisonErrorFunc);
            default:
                return (0, variable_utils_1.safelyGeneratePatternPreview)(this.expectedValue, variables, defaultComparisonErrorFunc);
        }
    }
    setOnFailure(onFailure) {
        if (this.onFailure === onFailure) {
            return false;
        }
        this.onFailure = onFailure;
        return true;
    }
    static generateStepFromMablStep(mablAssertStep, importer) {
        let wrapInConditionalType;
        if ((0, assert_utils_1.isIfConditionStep)(mablAssertStep)) {
            wrapInConditionalType = 'IF';
        }
        else if ((0, assert_utils_1.isElseIfConditionStep)(mablAssertStep)) {
            wrapInConditionalType = 'ELSEIF';
        }
        const findDescriptor = mablAssertStep.primaryAction.toDescriptor();
        let findOptions;
        if ((0, mablscriptFind_1.isFindElementDescriptor)(findDescriptor)) {
            findOptions = findDescriptor.findOptions;
        }
        let selectionType = 'element';
        let finalDescriptor;
        let extractionType;
        const extractedVar = maybeExtractVariableInfo(mablAssertStep, importer.variables);
        const finalVariable = extractedVar;
        switch (mablAssertStep.primaryAction.name) {
            case 'get_viewport':
                if (mablAssertStep.conditionAction.conditionDescriptor.conditionType ===
                    ConditionDescriptor_1.AssertionConditionField.AIPrompt) {
                    selectionType = 'viewport';
                    finalDescriptor = {
                        type: 'viewport',
                    };
                    extractionType = ExtractDescriptor_1.ExtractType.EXTRACT_PROMPT;
                }
                else {
                    throw new Error(`Assert step has a get_viewport primary action but is not an AI prompt: ${JSON.stringify(mablAssertStep)}`);
                }
                break;
            case 'find_cookie':
                if ((0, assert_utils_1.isFindCookieDescriptor)(findDescriptor)) {
                    finalDescriptor = {
                        type: 'cookie',
                        cookieSelector: {
                            ...findDescriptor.findTarget,
                        },
                    };
                }
                selectionType = 'cookie';
                break;
            case 'find_email':
                if ((0, assert_utils_1.isFindEmailDescriptor)(findDescriptor)) {
                    const descriptor = {
                        emailConfiguration: {},
                        emailSelector: {},
                        type: 'email',
                    };
                    const selectorProperties = ['from', 'subject', 'uuid', 'to_received', 'body_text'];
                    const preferenceProperties = [
                        'from',
                        'subject',
                        'to_received',
                        'body_text',
                    ];
                    selectorProperties.forEach((selectorProperty) => {
                        const value = findDescriptor.findTarget.selector[selectorProperty];
                        if (value !== undefined) {
                            descriptor.emailSelector[selectorProperty] = value;
                        }
                    });
                    preferenceProperties.forEach((preferenceProperty) => {
                        const value = findDescriptor.findTarget.configuration?.emailPreferences?.[preferenceProperty];
                        if (value !== undefined) {
                            if (!descriptor.emailConfiguration?.emailPreferences) {
                                descriptor.emailConfiguration.emailPreferences = {};
                            }
                            descriptor.emailConfiguration.emailPreferences[preferenceProperty] = value;
                        }
                    });
                    const lookbackTimeMsValue = findDescriptor.findTarget.configuration?.externalEmailPreferences
                        ?.lookbackTimeMs;
                    if (lookbackTimeMsValue !== undefined) {
                        if (!descriptor.emailConfiguration?.externalEmailPreferences) {
                            descriptor.emailConfiguration.externalEmailPreferences = {};
                        }
                        descriptor.emailConfiguration.externalEmailPreferences.lookbackTimeMs =
                            lookbackTimeMsValue;
                    }
                    finalDescriptor = (0, assertionUtil_1.cleanEmailFindDescriptorTree)(descriptor);
                }
                selectionType = 'email';
                break;
            case 'get_current_location':
                selectionType = 'location';
                finalDescriptor = {
                    type: 'location',
                };
                break;
            case 'get_variable_value':
                selectionType = 'variable';
                break;
            default:
                if (mablAssertStep.primaryAction instanceof FindAction_1.FindAction) {
                    const result = this.getFindDescriptorAndFindOptionsFromFindAction(mablAssertStep.primaryAction, importer);
                    finalDescriptor = result.findDescriptor;
                    findOptions = result.findOptions;
                    extractionType = getExtractionType(mablAssertStep);
                }
                else if (mablAssertStep.primaryAction instanceof MobileFindAction_1.MobileFindAction) {
                    if ((0, mablscriptFind_1.isWebViewFindElementDescriptor)(findDescriptor)) {
                        finalDescriptor = findDescriptor;
                    }
                    else {
                        finalDescriptor = {
                            configuration: findDescriptor.findTarget.configuration,
                            selector: findDescriptor.findTarget.selector,
                            type: findDescriptor.findType,
                        };
                    }
                    findOptions = findOptions;
                    extractionType = getExtractionType(mablAssertStep);
                }
                selectionType = 'element';
        }
        if ((0, assert_utils_1.isGetVariableValue)(mablAssertStep.primaryAction)) {
            return AssertVariableStep_1.default.generateStepFromMablStep(mablAssertStep, finalVariable);
        }
        let expectedValue = mablAssertStep.assertionValue ??
            (0, ConditionDescriptor_1.getOptionalComparatorValue)(mablAssertStep.conditionAction.conditionDescriptor);
        if (finalVariable?.value) {
            expectedValue = finalVariable.value;
        }
        if (typeof expectedValue === 'string') {
            expectedValue = (0, variable_utils_1.canonicalizeVariablePattern)(importer.variables, expectedValue);
        }
        let elementAttrProp = mablAssertStep.extractAction?.extractionAttribute;
        if (mablAssertStep.countAction ||
            mablAssertStep.actions.some((action) => action instanceof CountAction_1.CountAction)) {
            elementAttrProp = 'count';
        }
        const assertStep = new AssertStep(finalDescriptor, {
            selectionType,
            assertionType: mablAssertStep.assertionType ??
                (0, assert_utils_1.getOptionalComparisonType)(mablAssertStep.conditionAction.conditionDescriptor),
            assertionTarget: finalVariable ? 'variable' : 'element',
            caseInsensitive: (0, ConditionDescriptor_1.getOptionalConditionOptions)(mablAssertStep.conditionAction.conditionDescriptor)?.caseInsensitive,
            onFailure: mablAssertStep.onFailure,
            elementScreenshot: mablAssertStep.observationScope === AssertStep_1.ObservationScope.Element,
            elementAttrProp,
            expectedValue,
            extractionType,
            variable: finalVariable,
            wrapInConditional: !!wrapInConditionalType ? true : undefined,
            wrapInConditionalType: !!wrapInConditionalType
                ? wrapInConditionalType
                : undefined,
            findOptions,
            aiPrompt: mablAssertStep.aiPrompt ??
                ((0, ConditionDescriptor_1.isAIPromptCondition)(mablAssertStep.conditionAction.conditionDescriptor)
                    ? {
                        userPrompt: mablAssertStep.conditionAction.conditionDescriptor.userPrompt,
                        metaPrompt: mablAssertStep.conditionAction.conditionDescriptor.metaPrompt,
                        criteria: mablAssertStep.conditionAction.conditionDescriptor.criteria,
                    }
                    : undefined),
        });
        return assertStep;
    }
}
exports.default = AssertStep;
const defaultComparisonErrorFunc = (variableName) => {
    throw new Error(`Cannot resolve variable "${variableName?.replace(USER_NAMESPACE_REGEXP, '')}"`);
};
function maybeExtractVariableInfo(mablAssertStep, globalVariables) {
    if ((0, assert_utils_1.isGetVariableValue)(mablAssertStep.primaryAction) &&
        (0, MablSymbol_1.isMablSymbolObject)(mablAssertStep.primaryAction.variable)) {
        const extractedVariable = (0, BaseStep_1.resolveVariableValue)(mablAssertStep.primaryAction.variable.name, globalVariables);
        if (extractedVariable) {
            return extractedVariable;
        }
        const varName = mablAssertStep.primaryAction.variable.tokens.join('.');
        return {
            name: varName,
            humanizedName: (0, mablscriptFind_1.removeUserNamespace)(varName),
        };
    }
    if ((0, assert_utils_1.isComparisonConditionDescriptor)(mablAssertStep.conditionAction.conditionDescriptor) &&
        (0, MablSymbol_1.isMablSymbolObject)(mablAssertStep.conditionAction.conditionDescriptor.comparatorValue)) {
        const extractedVariable = (0, BaseStep_1.resolveVariableValue)(mablAssertStep.conditionAction.conditionDescriptor.comparatorValue.name, globalVariables);
        if (extractedVariable) {
            return extractedVariable;
        }
        const varName = mablAssertStep.conditionAction.conditionDescriptor.comparatorValue.tokens.join('.');
        return {
            name: varName,
            humanizedName: (0, mablscriptFind_1.removeUserNamespace)(varName),
        };
    }
    return;
}
function getExtractionType(mablAssertStep) {
    if (mablAssertStep.aiPrompt !== undefined ||
        mablAssertStep.conditionAction?.conditionDescriptor?.conditionType ===
            ConditionDescriptor_1.ConditionType.AIPrompt) {
        return ExtractDescriptor_1.ExtractType.EXTRACT_PROMPT;
    }
    return mablAssertStep.extractAction?.extractionType &&
        Object.values(ExtractDescriptor_1.ExtractType).includes(mablAssertStep.extractAction?.extractionType)
        ? mablAssertStep.extractAction?.extractionType
        : ExtractDescriptor_1.ExtractType.EXTRACT_ATTRIBUTE;
}
function humanizeAssertStep(step) {
    switch (step.assertionType) {
        case AssertStepTypes_1.default.PRESENT:
            return humanizeAssertPresent(step);
        case AssertStepTypes_1.default.NOT_PRESENT:
            return humanizeAssertNotPresent(step);
        case ConditionDescriptor_1.AssertionConditionField.AIPrompt:
        case undefined:
            return humanizeAssertPrompt(step);
        default:
            if (step.aiPrompt?.userPrompt) {
                return humanizeAssertPrompt(step);
            }
            return humanizeAssertAgainstValue(step);
    }
}
function humanizeAssertPresent(step) {
    if (step.wrapInConditional) {
        return `${humanConditionalPrefix(step)} ${(0, StepWithFind_1.humanizeFind)(step)} is present`;
    }
    if (step.findOptions?.waitUntil) {
        const waitUntilText = (0, StepWithFind_1.humanizeWaitUntil)(step);
        if (waitUntilText) {
            return `Wait ${waitUntilText}`;
        }
        const { timeoutSeconds } = step.findOptions.waitUntil;
        return `Wait up to ${timeoutSeconds} seconds until ${(0, StepWithFind_1.humanizeFind)(step)} is present`;
    }
    return `Assert presence of ${(0, StepWithFind_1.humanizeFind)(step)}`;
}
function humanizeAssertNotPresent(step) {
    if (step.wrapInConditional) {
        return `${humanConditionalPrefix(step)} ${(0, StepWithFind_1.humanizeFind)(step)} is absent`;
    }
    return `Assert absence of ${(0, StepWithFind_1.humanizeFind)(step)}`;
}
function humanizeAssertPrompt(step) {
    const userPromptForDisplay = step.aiPrompt?.userPrompt
        ? (0, mablscript_utils_1.repairOverEscapedMablscriptString)(step.aiPrompt.userPrompt.toString())
        : undefined;
    const userPromptForDisplaySingleLine = userPromptForDisplay?.replace(/\n/g, ' ');
    const humanizedAssertPrompt = userPromptForDisplaySingleLine
        ? `GenAI Assert: ${userPromptForDisplaySingleLine}`
        : 'GenAI assertion';
    if (step.wrapInConditional) {
        return `${humanConditionalPrefix(step)} ${humanizedAssertPrompt}`;
    }
    return humanizedAssertPrompt;
}
function humanizeAssertAgainstValue(step) {
    const humanizedFind = (0, StepWithFind_1.humanizeFind)(step);
    let assertionText;
    const prependedText = step.wrapInConditional
        ? humanConditionalPrefix(step)
        : 'Assert';
    const expectedValueStr = step.expectedValue?.toString() ?? '';
    switch (step.assertionTarget) {
        case 'variable': {
            const varDisplay = step.variable?.humanizedName || step.variable?.name;
            assertionText = `the value of the variable "${varDisplay}"`;
            break;
        }
        case 'element':
        default:
            if ((0, mablscriptFind_1.isLoneVariablePattern)(expectedValueStr)) {
                const rawVarName = (0, mablscriptFind_1.getVariableNameFromLoneVariablePattern)(expectedValueStr) ?? '';
                const varDisplay = (0, mablscriptFind_1.removeUserNamespace)(rawVarName);
                assertionText = `the value of the variable "${varDisplay}"`;
            }
            else {
                assertionText = (0, mablscriptFind_1.humanizeText)(step.expectedValue);
            }
    }
    const assertionTypeHumanized = (0, common_1.getAssertionHumanizedText)(step.assertionType);
    const attrPropText = step.findDescriptor.type === 'find_all' && step.elementAttrProp === 'count'
        ? step.elementAttrProp
        : `"${step.elementAttrProp}"`;
    return `${prependedText} ${attrPropText} of ${humanizedFind} ${assertionTypeHumanized} ${assertionText}`;
}
function humanConditionalPrefix(step) {
    return step.wrapInConditionalType === mablscript_step_types_1.CONDITIONAL_TYPE_ELSEIF
        ? `ELSE IF`
        : `IF`;
}
function isMobileWebViewAssertStep(step) {
    return (step.getStepType?.() === mablscript_step_types_1.StepType.ASSERTION &&
        (0, mablscriptFind_1.isWebViewFindElementDescriptor)(step.findDescriptor));
}
function isMobileFindAssertStep(step) {
    return (step.getStepType?.() === mablscript_step_types_1.StepType.ASSERTION &&
        (0, mablscriptFind_1.isMobileFindSpecification)(step.findDescriptor) &&
        !(step.wrapInConditional && step.assertionTarget === 'variable'));
}
function isAssertionStatus(value) {
    return value?.level && value?.message;
}
function assertStepToAIString(step) {
    const result = {};
    if (step.wrapInConditional) {
        result.stepType =
            step.wrapInConditionalType === mablscript_step_types_1.CONDITIONAL_TYPE_ELSEIF ? 'else_if' : 'if';
        result.condition = buildConditionObject(step);
    }
    else {
        result.stepType = step.stepType;
        Object.assign(result, buildConditionObject(step));
    }
    return (0, yaml_utils_1.toYaml)(result);
}
function buildConditionObject(step) {
    const condition = {};
    if (step.assertionType) {
        condition.assertion_type = step.assertionType;
    }
    if (step.aiPrompt?.userPrompt) {
        condition.prompt = step.aiPrompt.userPrompt;
        if (step.aiPrompt.metaPrompt) {
            condition.meta_prompt = step.aiPrompt.metaPrompt;
        }
        if (step.aiPrompt.criteria && step.aiPrompt.criteria.length > 0) {
            condition.criteria = step.aiPrompt.criteria;
        }
    }
    if (step.assertionType !== AssertStepTypes_1.default.PRESENT &&
        step.assertionType !== AssertStepTypes_1.default.NOT_PRESENT &&
        !step.aiPrompt?.userPrompt) {
        if (step.elementAttrProp) {
            condition.attribute = step.elementAttrProp;
        }
        if (step.assertionTarget === 'variable' && step.variable) {
            condition.expected_variable =
                step.variable.humanizedName || step.variable.name;
        }
        else if (step.expectedValue !== undefined) {
            condition.expected_value = step.expectedValue;
        }
    }
    if (step.caseInsensitive) {
        condition.case_insensitive = true;
    }
    if (step.onFailure && step.onFailure !== AssertStep_1.OnFailure.FailImmediately) {
        condition.on_failure = step.onFailure;
    }
    if (step.findDescriptor) {
        condition.target = (0, StepWithFind_1.findDescriptorToAIObject)(step.findDescriptor, step.findOptions);
    }
    return condition;
}
