import { MAX_PASS_CRITERIA_DEPTH } from "../types/utility.js";

//#region src/evaluation/pass-criteria-evaluator.ts
function isGroup(node) {
	return "conditions" in node && Array.isArray(node.conditions);
}
function evaluateLeaf(condition, result) {
	const fieldValue = result[condition.field];
	if (!(condition.field in result)) return {
		passed: false,
		failedLeaves: [],
		errors: [`Field '${condition.field}' does not exist in output`]
	};
	if (typeof condition.value === "boolean") {
		if (typeof fieldValue !== "boolean") return {
			passed: false,
			failedLeaves: [],
			errors: [`Field '${condition.field}' is not a boolean (got ${typeof fieldValue})`]
		};
		let passed$1 = false;
		if (condition.operator === "=") passed$1 = fieldValue === condition.value;
		else passed$1 = fieldValue !== condition.value;
		return {
			passed: passed$1,
			failedLeaves: passed$1 ? [] : [condition],
			errors: []
		};
	}
	if (typeof fieldValue !== "number" || !Number.isFinite(fieldValue)) return {
		passed: false,
		failedLeaves: [],
		errors: [`Field '${condition.field}' is not a finite number (got ${typeof fieldValue === "number" ? String(fieldValue) : typeof fieldValue})`]
	};
	const numericValue = condition.value;
	const op = condition.operator;
	let passed = false;
	switch (op) {
		case ">":
			passed = fieldValue > numericValue;
			break;
		case "<":
			passed = fieldValue < numericValue;
			break;
		case ">=":
			passed = fieldValue >= numericValue;
			break;
		case "<=":
			passed = fieldValue <= numericValue;
			break;
		case "=":
			passed = fieldValue === numericValue;
			break;
		case "!=":
			passed = fieldValue !== numericValue;
			break;
		default: passed = false;
	}
	return {
		passed,
		failedLeaves: passed ? [] : [condition],
		errors: []
	};
}
function evaluateNode(node, result, depth) {
	if (!isGroup(node)) return evaluateLeaf(node, result);
	if (depth > MAX_PASS_CRITERIA_DEPTH) return {
		passed: false,
		failedLeaves: [],
		errors: [`Pass criteria exceeds maximum nesting depth of ${MAX_PASS_CRITERIA_DEPTH}`]
	};
	if (node.conditions.length === 0) return {
		passed: true,
		failedLeaves: [],
		errors: []
	};
	const childResults = node.conditions.map((child) => evaluateNode(child, result, isGroup(child) ? depth + 1 : depth));
	const allErrors = childResults.flatMap((r) => r.errors);
	if (node.operator === "and") return {
		passed: childResults.every((r) => r.passed),
		failedLeaves: childResults.flatMap((r) => r.failedLeaves),
		errors: allErrors
	};
	const passed = childResults.some((r) => r.passed);
	return {
		passed,
		failedLeaves: passed ? [] : childResults.flatMap((r) => r.failedLeaves),
		errors: allErrors
	};
}
function evaluatePassCriteria(criteria, evaluationResult) {
	if (!criteria || !criteria.conditions || criteria.conditions.length === 0) return { status: "no_criteria" };
	const nodeResult = evaluateNode(criteria, evaluationResult, 0);
	if (nodeResult.errors.length > 0) return {
		status: "no_criteria",
		configurationErrors: nodeResult.errors
	};
	return {
		status: nodeResult.passed ? "passed" : "failed",
		failedConditions: nodeResult.failedLeaves.length > 0 ? nodeResult.failedLeaves : void 0
	};
}

//#endregion
export { evaluatePassCriteria };