"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateStepStructure = validateStepStructure;
exports.validateStructure = validateStructure;
const errors_1 = require("../errors");
const json_steps_1 = require("../schemas/json-steps");
const step_registry_1 = require("../schemas/step-registry");
const shared_1 = require("../schemas/steps/shared");
function validateEnvelope(input) {
    const parsed = json_steps_1.jsonStepsEnvelopeSchema.safeParse(input);
    if (!parsed.success) {
        return (0, errors_1.fromZodIssues)(parsed.error.issues);
    }
    return (0, errors_1.emptyResult)();
}
function validateStepStructure(step, stepIndex, options) {
    const pathPrefix = ['steps', stepIndex];
    if (typeof step !== 'object' || !step || Array.isArray(step)) {
        return (0, errors_1.errorResult)(pathPrefix, 'Step must be an object with exactly one key (the step type name)', 'step.not_object');
    }
    const keys = Object.keys(step);
    if (keys.length === 0) {
        return (0, errors_1.errorResult)(pathPrefix, 'Step object must not be empty', 'step.empty');
    }
    if (keys.length > 1) {
        return (0, errors_1.errorResult)(pathPrefix, `Step must have exactly one key (the step type name), found ${keys.length}: ${keys.join(', ')}`, 'step.multiple_keys');
    }
    const stepTypeName = keys[0];
    const stepDescriptor = step[stepTypeName];
    if (!(0, step_registry_1.isKnownStepType)(stepTypeName, options.testType)) {
        return (0, errors_1.errorResult)([...pathPrefix, stepTypeName], `Unknown step type: "${stepTypeName}"`, 'step.unknown_type');
    }
    if (typeof stepDescriptor !== 'object' ||
        !stepDescriptor ||
        Array.isArray(stepDescriptor)) {
        return (0, errors_1.errorResult)([...pathPrefix, stepTypeName], 'Step descriptor must be an object', 'step.descriptor_not_object');
    }
    const schema = (0, step_registry_1.getStepSchema)(stepTypeName, options.testType);
    if (schema) {
        const parsed = schema.safeParse(stepDescriptor);
        if (!parsed.success) {
            return (0, errors_1.fromZodIssues)(parsed.error.issues, [...pathPrefix, stepTypeName]);
        }
    }
    if (options.testType === 'browser' &&
        shared_1.BROWSER_FIND_REQUIRED_STEP_TYPES.has(stepTypeName)) {
        if (!(0, shared_1.hasBrowserFindLocator)(stepDescriptor)) {
            return (0, errors_1.errorResult)([...pathPrefix, stepTypeName], `${stepTypeName} step requires a browser find — set either \`find\` (modern) or \`selector\` (legacy).`, 'step.missing_browser_find');
        }
    }
    if (stepTypeName === 'StepGroup') {
        const descriptor = stepDescriptor;
        if (Array.isArray(descriptor.steps)) {
            const nestedResults = descriptor.steps.map((nestedStep, nestedIndex) => {
                const nestedResult = validateStepStructure(nestedStep, nestedIndex, options);
                for (const err of nestedResult.errors) {
                    err.path = [...pathPrefix, 'StepGroup', ...err.path];
                }
                for (const warn of nestedResult.warnings) {
                    warn.path = [...pathPrefix, 'StepGroup', ...warn.path];
                }
                return nestedResult;
            });
            return (0, errors_1.mergeResults)((0, errors_1.emptyResult)(), ...nestedResults);
        }
    }
    return (0, errors_1.emptyResult)();
}
function validateStructure(input, options) {
    const envelopeResult = validateEnvelope(input);
    if (!envelopeResult.valid) {
        return envelopeResult;
    }
    const steps = input.steps;
    const stepResults = steps.map((step, index) => validateStepStructure(step, index, options));
    return (0, errors_1.mergeResults)(envelopeResult, ...stepResults);
}
