/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
const require_componentStatePseudoStates = require("./componentStatePseudoStates.cjs");
const require_generateSchemaKey = require("./generateSchemaKey.cjs");
const require_resolvePropertyStates = require("./resolvePropertyStates.cjs");
const require_variantConfigGuards = require("./variantConfigGuards.cjs");
const require_util = require("../../../fixtures/src/util.cjs");
//#region ../automated-config/dist/utils/buildConfigSchema.js
/*! © 2026 Yahoo, Inc. UDS Default Config v0.0.0-development */
/**
* Builds the per-state schema entries for one property on one variant option.
* Each state slot (rest, hover, invalid&hover, ...) gets the property's
* default value as a starting point so the Configurator UI has something to
* render before users tweak.
*
* Per-state CSS emission depends on the emit mode (`exhaustive` by default,
* `selective` opt-in) and on the `isEnabled` flag this builder writes:
*   - `rest` always emits in both modes (no flag needed; CSS gen treats rest
*     as enabled).
*   - Under EXHAUSTIVE (the default) on `atomicStates` layers, every declared
*     non-rest state emits a rule regardless of `isEnabled`; its value is
*     cascade-resolved (see `resolveSlotByCascade`), so there are no gaps.
*     `isEnabled` there only selects which value a state resolves to, not
*     whether it emits.
*   - Under SELECTIVE (and legacy `pseudoStates`) emission, non-rest slots
*     emit only when `isEnabled === true`.
*   - `skipRestState` properties have no rest fallback, so every populated
*     state slot must emit; we set `isEnabled: true` on each.
*   - Otherwise, auto-populated non-rest slots ship with no flag — under
*     selective they're off until a designer enables them via the
*     configurator's per-property checkbox (which sets or clears this flag
*     through the setter); under exhaustive they still emit via the cascade.
*/
function buildPropertyStateMap(layer, property, variantOption, excludedStates = []) {
	const stateMap = {};
	const excluded = new Set(excludedStates);
	const states = require_resolvePropertyStates.resolvePropertyStates(layer, property);
	const fixtureType = findFixtureType(property, variantOption);
	const value = property.defaults[variantOption];
	const skipRestState = property.skipRestState === true;
	const isTextVariant = propertyVariesOnlyAtRest(property);
	for (const state of states) {
		if (excluded.has(state)) continue;
		if (isTextVariant && state !== "rest") continue;
		stateMap[state] = skipRestState ? {
			type: fixtureType,
			valueType: "alias",
			value,
			isEnabled: true
		} : {
			type: fixtureType,
			valueType: "alias",
			value
		};
	}
	return stateMap;
}
/**
* Whether a property's non-rest slots are stored SPARSELY — never pre-populated
* by the schema builder, only persisted when a designer authors an explicit
* per-state override (resolved via the cascade otherwise). `textVariant` is the
* only such property today: its non-rest "Emphasized" overrides are created
* lazily in the configurator rather than seeded for every state.
*
* Consulted by the schema builder ({@link buildPropertyStateMap}) to keep the
* stored config compact. CSS emission does NOT special-case these properties:
* exhaustive emission walks every declared state and resolves each through the
* cascade (`resolveSlotByCascade`), so an authored non-rest override emits a
* rule that renders while unauthored states resolve back to rest.
*/
function propertyVariesOnlyAtRest(property) {
	return property.name === "textVariant";
}
function isOptionalInDefaultSchema(property) {
	return property.optionalInDefaultSchema === true;
}
/** Resolves the fixture type by finding which value set contains the given value */
function findFixtureTypeForValue(property, value) {
	const index = property.values.findIndex((arr) => arr.includes(value));
	const fixtureType = property.typeOfFixture[index === -1 ? 0 : index];
	const arbitraryFixture = require_util.getArbitraryFixture(fixtureType);
	if (arbitraryFixture && !require_util.validateArbitraryValue(arbitraryFixture, value)) throw new Error(`Invalid value "${value}" for property "${property.name}": does not satisfy ${fixtureType} constraints`);
	return fixtureType;
}
/** Resolves the fixture type for a property's variant by finding which value set contains the default value */
function findFixtureType(property, variantKey) {
	return findFixtureTypeForValue(property, property.defaults[variantKey]);
}
/**
* Walk a set of layers and emit schema entries keyed by layer (no
* component-state segment). Shared between `VariantConfigWithProperties` and
* the optional top-level `layers` field on `VariantConfigWithComponentStates`.
*/
function emitUniversalLayerSchema(result, layers, variantKey, variantOption, subComponentName) {
	for (const layerKey in layers) {
		const layer = layers[layerKey];
		const schemaKey = require_generateSchemaKey.generateSchemaKey({
			variantKey,
			variantValue: variantOption,
			layer: layerKey,
			subComponentName
		});
		result.variables[schemaKey] = {};
		for (const propertyKey in layer.properties) {
			const property = layer.properties[propertyKey];
			if (isOptionalInDefaultSchema(property)) continue;
			result.variables[schemaKey] = {
				...result.variables[schemaKey],
				[propertyKey]: buildPropertyStateMap(layer, property, variantOption)
			};
		}
	}
}
/** Builds component schema from ComponentConfig at runtime */
function buildConfigSchema(config) {
	const result = {};
	const defaultsObj = {};
	for (const variantKey in config.variants) defaultsObj[variantKey] = config.variants[variantKey].default;
	result.defaults = defaultsObj;
	result.variables = {};
	for (const variantKey in config.variants) {
		const variantConfig = config.variants[variantKey];
		for (const variantOption of variantConfig.options) if (require_variantConfigGuards.isVariantConfigWithComponentStates(variantConfig)) {
			if (variantConfig.layers) emitUniversalLayerSchema(result, variantConfig.layers, variantKey, variantOption);
			const componentStates = variantConfig.componentStates;
			for (const componentStateKey in componentStates) {
				const componentState = componentStates[componentStateKey];
				for (const componentStateOption of componentState.options) {
					const excludedLayers = new Set(require_componentStatePseudoStates.getExcludedLayersForComponentStateOption(componentState, componentStateOption));
					for (const layerKey in componentState.layers) {
						if (excludedLayers.has(layerKey)) continue;
						const layer = componentState.layers[layerKey];
						const schemaKey = require_generateSchemaKey.generateSchemaKey({
							variantKey,
							variantValue: variantOption,
							componentStateKey,
							componentStateValue: componentStateOption,
							layer: layerKey
						});
						result.variables[schemaKey] = {};
						for (const propertyKey in layer.properties) {
							const property = layer.properties[propertyKey];
							if (isOptionalInDefaultSchema(property)) continue;
							result.variables[schemaKey] = {
								...result.variables[schemaKey],
								[propertyKey]: buildPropertyStateMap(layer, property, variantOption, require_componentStatePseudoStates.getExcludedPseudoStatesForComponentStateOption(componentState, componentStateOption))
							};
						}
					}
				}
			}
		} else if (require_variantConfigGuards.isVariantConfigWithProperties(variantConfig)) {
			if (variantConfig.variantProperties) {
				const variantSchemaKey = `${variantKey}/${variantOption}`;
				result.variables[variantSchemaKey] = result.variables[variantSchemaKey] ?? {};
				for (const propertyKey in variantConfig.variantProperties) {
					const property = variantConfig.variantProperties[propertyKey];
					if (isOptionalInDefaultSchema(property)) continue;
					result.variables[variantSchemaKey] = {
						...result.variables[variantSchemaKey],
						[propertyKey]: buildPropertyStateMap({
							label: "",
							properties: {}
						}, property, variantOption)
					};
				}
			}
			emitUniversalLayerSchema(result, variantConfig.layers, variantKey, variantOption);
		}
	}
	if (config.subComponents) {
		const { subComponents } = config;
		for (const subComponentKey in subComponents) for (const variantKey in subComponents[subComponentKey].variants) {
			const variantConfig = subComponents[subComponentKey].variants[variantKey];
			result.defaults[variantKey] = variantConfig.default;
			for (const variantOption of variantConfig.options) if (require_variantConfigGuards.isVariantConfigWithComponentStates(variantConfig)) {
				if (variantConfig.layers) emitUniversalLayerSchema(result, variantConfig.layers, variantKey, variantOption, subComponentKey);
				const componentStates = variantConfig.componentStates;
				for (const componentStateKey in componentStates) {
					const componentState = componentStates[componentStateKey];
					for (const componentStateOption of componentState.options) {
						const excludedLayers = new Set(require_componentStatePseudoStates.getExcludedLayersForComponentStateOption(componentState, componentStateOption));
						for (const layerKey in componentState.layers) {
							if (excludedLayers.has(layerKey)) continue;
							const layer = componentState.layers[layerKey];
							const schemaKey = require_generateSchemaKey.generateSchemaKey({
								variantKey,
								variantValue: variantOption,
								componentStateKey,
								componentStateValue: componentStateOption,
								layer: layerKey,
								subComponentName: subComponentKey
							});
							result.variables[schemaKey] = {};
							for (const propertyKey in layer.properties) {
								const property = layer.properties[propertyKey];
								if (isOptionalInDefaultSchema(property)) continue;
								result.variables[schemaKey] = {
									...result.variables[schemaKey],
									[propertyKey]: buildPropertyStateMap(layer, property, variantOption, require_componentStatePseudoStates.getExcludedPseudoStatesForComponentStateOption(componentState, componentStateOption))
								};
							}
						}
					}
				}
			} else if (require_variantConfigGuards.isVariantConfigWithProperties(variantConfig)) emitUniversalLayerSchema(result, variantConfig.layers, variantKey, variantOption, subComponentKey);
		}
	}
	return result;
}
//#endregion
exports.buildConfigSchema = buildConfigSchema;
exports.findFixtureType = findFixtureType;
exports.findFixtureTypeForValue = findFixtureTypeForValue;
