import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import { parseBrowserPipeline } from "./schema.js";
import { resolveTemplateDeep } from "./template.js";
import { addStepResult, createPipelineOutput, formatPipelineResult } from "./output.js";
//#region src/browser/pipeline/runner.ts
init_logger();
const log = createLogger("PipelineRunner");
/**
* Parse and validate a pipeline YAML without executing it.
*/
function validateBrowserPipeline(yamlSource, registry) {
	const parseResult = parseBrowserPipeline(yamlSource);
	if (!parseResult.ok || !parseResult.document) return {
		ok: false,
		errors: parseResult.errors
	};
	const doc = parseResult.document;
	const errors = [];
	if (registry) {
		for (let i = 0; i < doc.pipeline.length; i++) {
			const step = doc.pipeline[i];
			if (!registry.has(step.action)) errors.push({
				path: `pipeline[${i}]`,
				message: `Unknown action: "${step.action}"`
			});
		}
		if (doc.onError) for (let i = 0; i < doc.onError.length; i++) {
			const step = doc.onError[i];
			if (!registry.has(step.action)) errors.push({
				path: `on_error[${i}]`,
				message: `Unknown action: "${step.action}"`
			});
		}
	}
	if (errors.length > 0) return {
		ok: false,
		document: doc,
		errors
	};
	return {
		ok: true,
		document: doc,
		errors: []
	};
}
function resolveArgs(doc, overrides) {
	const resolved = {};
	for (const [key, def] of Object.entries(doc.args)) if (key in overrides) resolved[key] = overrides[key];
	else if (def.default !== void 0) resolved[key] = def.default;
	else if (def.required) throw new Error(`Missing required arg: ${key}`);
	for (const [key, val] of Object.entries(overrides)) if (!(key in resolved)) resolved[key] = val;
	return resolved;
}
async function executeStep(step, templateCtx, actionCtx, registry) {
	let resolvedArgs;
	if (typeof step.args === "string") {
		const resolved = resolveTemplateDeep(step.args, templateCtx);
		if (step.action === "evaluate" || step.action === "eval" || step.action === "console") resolvedArgs = { javascript: resolved };
		else resolvedArgs = { value: resolved };
	} else resolvedArgs = resolveTemplateDeep(step.args, templateCtx);
	return registry.execute(step.action, actionCtx, resolvedArgs);
}
/**
* Run a browser pipeline from YAML source.
*
* @param yamlSource - Raw YAML text.
* @param argOverrides - Runtime argument overrides.
* @param ctx - Browser action context (page, manager, config, etc.).
* @param registry - Action registry.
* @param dryRun - When true, only validate without executing.
*/
async function runBrowserPipeline(yamlSource, argOverrides, ctx, registry, dryRun = false) {
	const validation = validateBrowserPipeline(yamlSource, registry);
	if (!validation.ok || !validation.document) return {
		ok: false,
		action: "pipeline",
		error: {
			code: "VALIDATION_FAILED",
			message: validation.errors.map((e) => `${e.path}: ${e.message}`).join("\n")
		}
	};
	const doc = validation.document;
	if (dryRun) return {
		ok: true,
		action: "pipeline",
		text: `Pipeline "${doc.name}" validated successfully (${doc.pipeline.length} steps).`,
		data: {
			name: doc.name,
			steps: doc.pipeline.length,
			args: Object.keys(doc.args)
		}
	};
	let resolvedArgs;
	try {
		resolvedArgs = resolveArgs(doc, argOverrides);
	} catch (e) {
		return {
			ok: false,
			action: "pipeline",
			error: {
				code: "ARG_RESOLUTION_FAILED",
				message: e instanceof Error ? e.message : String(e)
			}
		};
	}
	const output = createPipelineOutput(doc.name);
	let data = void 0;
	const templateCtx = {
		args: resolvedArgs,
		data: void 0
	};
	ctx.pipelineData = void 0;
	log.info({
		pipeline: doc.name,
		steps: doc.pipeline.length
	}, `Running pipeline: ${doc.name}`);
	for (let i = 0; i < doc.pipeline.length; i++) {
		if (ctx.signal?.aborted) {
			output.ok = false;
			output.error = {
				step: i,
				action: "abort",
				code: "ABORTED",
				message: "Pipeline aborted"
			};
			break;
		}
		const step = doc.pipeline[i];
		const result = await executeStep(step, templateCtx, ctx, registry);
		addStepResult(output, i, result);
		if (result.ok && result.data !== void 0) {
			data = result.data;
			templateCtx.data = data;
			ctx.pipelineData = data;
		}
		if (step.action === "output" && result.ok && result.data !== void 0) output.data = result.data;
		if (!result.ok) {
			templateCtx.error = result.error ? {
				code: result.error.code,
				message: result.error.message
			} : void 0;
			break;
		}
	}
	if (output.ok && output.data === void 0) output.data = data;
	if (!output.ok && doc.onError && doc.onError.length > 0) {
		log.info({ pipeline: doc.name }, "Running on_error diagnostics");
		for (const step of doc.onError) {
			if (ctx.signal?.aborted) break;
			try {
				const result = await executeStep(step, templateCtx, ctx, registry);
				if (result.artifacts) output.artifacts.push(...result.artifacts);
			} catch {}
		}
	}
	return formatPipelineResult(output);
}
//#endregion
export { runBrowserPipeline, validateBrowserPipeline };

//# sourceMappingURL=runner.js.map