const require_utils = require('./utils-CR1ToTMW.js');
const require_isRuleGroup = require('./isRuleGroup-Cjk1Q2mj.js');
const require_convertQuery = require('./convertQuery-DRldbzhZ.js');
const require_prepareQueryObjects = require('./prepareQueryObjects-BxWvIPI4.js');

//#region src/utils/parseJsonLogic/utils.ts
const isJsonLogicVar = (logic) => require_isRuleGroup.isPojo(logic) && "var" in logic;
const isRQBJsonLogicVar = (logic) => isJsonLogicVar(logic) && typeof logic.var === "string";
const isJsonLogicEqual = (logic) => require_isRuleGroup.isPojo(logic) && "==" in logic;
const isJsonLogicStrictEqual = (logic) => require_isRuleGroup.isPojo(logic) && "===" in logic;
const isJsonLogicNotEqual = (logic) => require_isRuleGroup.isPojo(logic) && "!=" in logic;
const isJsonLogicStrictNotEqual = (logic) => require_isRuleGroup.isPojo(logic) && "!==" in logic;
const isJsonLogicNegation = (logic) => require_isRuleGroup.isPojo(logic) && "!" in logic;
const isJsonLogicDoubleNegation = (logic) => require_isRuleGroup.isPojo(logic) && "!!" in logic;
const isJsonLogicOr = (logic) => require_isRuleGroup.isPojo(logic) && "or" in logic;
const isJsonLogicAnd = (logic) => require_isRuleGroup.isPojo(logic) && "and" in logic;
const isJsonLogicGreaterThan = (logic) => require_isRuleGroup.isPojo(logic) && ">" in logic;
const isJsonLogicGreaterThanOrEqual = (logic) => require_isRuleGroup.isPojo(logic) && ">=" in logic;
const isJsonLogicLessThan = (logic) => require_isRuleGroup.isPojo(logic) && "<" in logic && logic["<"].length === 2;
const isJsonLogicLessThanOrEqual = (logic) => require_isRuleGroup.isPojo(logic) && "<=" in logic && logic["<="].length === 2;
const isJsonLogicInArray = (logic) => require_isRuleGroup.isPojo(logic) && "in" in logic && Array.isArray(logic.in[1]);
const isJsonLogicInString = (logic) => require_isRuleGroup.isPojo(logic) && "in" in logic && !Array.isArray(logic.in[1]);
const isJsonLogicAll = (logic) => require_isRuleGroup.isPojo(logic) && "all" in logic;
const isJsonLogicNone = (logic) => require_isRuleGroup.isPojo(logic) && "none" in logic;
const isJsonLogicSome = (logic) => require_isRuleGroup.isPojo(logic) && "some" in logic;
const isJsonLogicBetweenExclusive = (logic) => require_isRuleGroup.isPojo(logic) && "<" in logic && Array.isArray(logic["<"]) && logic["<"].length === 3;
const isJsonLogicBetweenInclusive = (logic) => require_isRuleGroup.isPojo(logic) && "<=" in logic && Array.isArray(logic["<="]) && logic["<="].length === 3;
const isRQBJsonLogicStartsWith = (logic) => require_isRuleGroup.isPojo(logic) && "startsWith" in logic;
const isRQBJsonLogicEndsWith = (logic) => require_isRuleGroup.isPojo(logic) && "endsWith" in logic;

//#endregion
//#region src/utils/parseJsonLogic/parseJsonLogic.ts
const emptyRuleGroup = {
	combinator: "and",
	rules: []
};
function parseJsonLogic(rqbJsonLogic, options = {}) {
	const fieldsFlat = require_prepareQueryObjects.getFieldsArray(options.fields);
	const { getValueSources, listsAsArrays, jsonLogicOperations } = options;
	const fieldIsValid = (fieldName, operator, subordinateFieldName) => require_prepareQueryObjects.fieldIsValidUtil({
		fieldName,
		fieldsFlat,
		operator,
		subordinateFieldName,
		getValueSources
	});
	function processLogic(logic, outermost) {
		if (outermost && !require_isRuleGroup.isPojo(logic)) return false;
		const [key, keyValue] = Object.entries(logic || {})?.[0] ?? [];
		if (jsonLogicOperations && require_utils.objectKeys(jsonLogicOperations).includes(key)) {
			const rule$1 = jsonLogicOperations[key](keyValue);
			return rule$1 ? outermost && !require_isRuleGroup.isRuleGroup(rule$1) ? {
				combinator: "and",
				rules: [rule$1]
			} : rule$1 : false;
		}
		if (isJsonLogicAnd(logic)) return {
			combinator: "and",
			rules: logic.and.map((l) => processLogic(l)).filter(Boolean)
		};
		else if (isJsonLogicOr(logic)) return {
			combinator: "or",
			rules: logic.or.map((l) => processLogic(l)).filter(Boolean)
		};
		else if (isJsonLogicNegation(logic)) {
			const rule$1 = processLogic(logic["!"]);
			if (rule$1) {
				if (!require_isRuleGroup.isRuleGroupType(rule$1) && (rule$1.operator === "between" || rule$1.operator === "in" || rule$1.operator === "contains" || rule$1.operator === "beginsWith" || rule$1.operator === "endsWith")) {
					const newRule = {
						...rule$1,
						operator: require_utils.defaultOperatorNegationMap[rule$1.operator]
					};
					if (outermost) return {
						combinator: "and",
						rules: [newRule]
					};
					return newRule;
				} else if (isJsonLogicBetweenExclusive(logic["!"]) || require_isRuleGroup.isRuleGroupType(rule$1)) return {
					...rule$1,
					not: true
				};
				return {
					combinator: "and",
					rules: [rule$1],
					not: true
				};
			}
			return false;
		} else if (isJsonLogicDoubleNegation(logic)) return processLogic(logic["!!"]) || false;
		let rule = false;
		let field = "";
		let operator = "=";
		let value = "";
		let valueSource = void 0;
		if (isJsonLogicEqual(logic) || isJsonLogicStrictEqual(logic) || isJsonLogicNotEqual(logic) || isJsonLogicStrictNotEqual(logic) || isJsonLogicGreaterThan(logic) || isJsonLogicGreaterThanOrEqual(logic) || isJsonLogicLessThan(logic) || isJsonLogicLessThanOrEqual(logic) || isJsonLogicInString(logic) || isRQBJsonLogicStartsWith(logic) || isRQBJsonLogicEndsWith(logic)) {
			const [first, second] = keyValue;
			if (isRQBJsonLogicVar(first) && !require_isRuleGroup.isPojo(second)) {
				field = first.var;
				value = second;
			} else if (!require_isRuleGroup.isPojo(first) && isRQBJsonLogicVar(second)) {
				field = second.var;
				value = first;
			} else if (isRQBJsonLogicVar(first) && isRQBJsonLogicVar(second)) {
				field = first.var;
				value = second.var;
				valueSource = "field";
			} else return false;
			if (isJsonLogicEqual(logic) || isJsonLogicStrictEqual(logic)) operator = value === null ? "null" : "=";
			else if (isJsonLogicNotEqual(logic) || isJsonLogicStrictNotEqual(logic)) operator = value === null ? "notNull" : "!=";
			else if (isJsonLogicInString(logic)) operator = "contains";
			else if (isRQBJsonLogicStartsWith(logic)) operator = "beginsWith";
			else if (isRQBJsonLogicEndsWith(logic)) operator = "endsWith";
			else operator = key;
			if (fieldIsValid(field, operator, valueSource === "field" ? value : void 0)) rule = {
				field,
				operator,
				value,
				valueSource
			};
		} else if (isJsonLogicAll(logic) && isRQBJsonLogicVar(logic["all"][0]) || isJsonLogicNone(logic) && isRQBJsonLogicVar(logic["none"][0]) || isJsonLogicSome(logic) && isRQBJsonLogicVar(logic["some"][0])) {
			const match = { mode: isJsonLogicNone(logic) ? "none" : isJsonLogicSome(logic) ? "some" : "all" };
			const [{ var: field$1 }, operation] = logic[match.mode];
			const matcher = processLogic(operation);
			if (!matcher) return false;
			rule = {
				field: field$1,
				operator: "=",
				match,
				value: require_isRuleGroup.isRuleGroup(matcher) ? matcher : {
					combinator: "and",
					rules: [matcher]
				}
			};
		} else if (isJsonLogicBetweenExclusive(logic) && isRQBJsonLogicVar(logic["<"][1])) {
			field = logic["<"][1].var;
			const values = [logic["<"][0], logic["<"][2]];
			// istanbul ignore else
			if (values.every((v) => isRQBJsonLogicVar(v)) || values.every((el) => typeof el === "string") || values.every((el) => typeof el === "number") || values.every((el) => typeof el === "boolean")) return processLogic({ and: [{ ">": [{ var: field }, values[0]] }, { "<": [{ var: field }, values[1]] }] }) || false;
		} else if (isJsonLogicBetweenInclusive(logic) && isRQBJsonLogicVar(logic["<="][1])) {
			field = logic["<="][1].var;
			operator = "between";
			const values = [logic["<="][0], logic["<="][2]];
			if (logic["<="].every((v) => isRQBJsonLogicVar(v))) {
				const vars = values;
				valueSource = "field";
				const fieldList = vars.map((el) => el.var).filter((sf) => fieldIsValid(field, operator, sf));
				value = listsAsArrays ? fieldList : require_utils.joinWith(fieldList, ",");
			} else if (values.every((el) => typeof el === "string") || values.every((el) => typeof el === "number") || values.every((el) => typeof el === "boolean")) value = listsAsArrays ? values : require_utils.joinWith(values.map((el) => `${el}`), ",");
			if (fieldIsValid(field, operator) && value.length >= 2) rule = {
				field,
				operator,
				value,
				valueSource
			};
		} else if (isJsonLogicInArray(logic) && isRQBJsonLogicVar(keyValue[0])) {
			field = keyValue[0].var;
			operator = "in";
			if (logic.in[1].every((v) => isRQBJsonLogicVar(v))) {
				valueSource = "field";
				const fieldList = logic.in[1].map((el) => el.var).filter((sf) => fieldIsValid(field, operator, sf));
				value = listsAsArrays ? fieldList : require_utils.joinWith(fieldList, ",");
			} else if (logic.in[1].every((el) => typeof el === "string") || logic.in[1].every((el) => typeof el === "number") || logic.in[1].every((el) => typeof el === "boolean")) value = listsAsArrays ? logic.in[1] : require_utils.joinWith(logic.in[1].map((el) => `${el}`), ",");
			// istanbul ignore else
			if (value.length > 0) rule = {
				field,
				operator,
				value,
				valueSource
			};
		}
		return rule ? outermost ? {
			combinator: "and",
			rules: [rule]
		} : rule : false;
	}
	const prepare = options.generateIDs ? require_prepareQueryObjects.prepareRuleGroup : (g) => g;
	let logicRoot = rqbJsonLogic;
	if (typeof rqbJsonLogic === "string") try {
		logicRoot = JSON.parse(rqbJsonLogic);
	} catch {
		return prepare(emptyRuleGroup);
	}
	const finalQuery = processLogic(logicRoot, true) || emptyRuleGroup;
	return prepare(options.independentCombinators ? require_convertQuery.convertToIC(finalQuery) : finalQuery);
}

//#endregion
exports.parseJsonLogic = parseJsonLogic;
//# sourceMappingURL=parseJsonLogic.js.map