/*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
const require_runtime = require("../../../_virtual/_rolldown/runtime.cjs");
const require_entryPoints = require("../../../utils/entryPoints.cjs");
const require_index = require("../../../motion-tokens/dist/index.cjs");
const require_hookMetadata = require("../../../runtimeConfig/hookMetadata.cjs");
let node_fs = require("node:fs");
let node_path = require("node:path");
node_path = require_runtime.__toESM(node_path, 1);
let fast_glob = require("fast-glob");
fast_glob = require_runtime.__toESM(fast_glob, 1);
let ts_morph = require("ts-morph");
//#region src/purger/optimized/utils/componentAnalyzer.ts
/**
* Known UDS component names (populated by scanning)
*/
let knownComponents = null;
/**
* Map of component name -> file path
*/
let componentPaths = null;
let scannedComponentsDir = null;
const hasImportQuery = (moduleSpecifier) => moduleSpecifier.includes("?");
const scanComponentFilePaths = async (componentsDir) => (0, fast_glob.default)(require_entryPoints.getAllowedEntryFileGlobPatterns(), {
	cwd: componentsDir,
	absolute: true
});
/**
* Scan src/components to build a map of all component files
*/
const scanComponentFiles = async (componentsDir) => {
	if (componentPaths && scannedComponentsDir === componentsDir) return componentPaths;
	componentPaths = /* @__PURE__ */ new Map();
	knownComponents = /* @__PURE__ */ new Set();
	scannedComponentsDir = componentsDir;
	const nextComponentPaths = componentPaths;
	const nextKnownComponents = knownComponents;
	(await scanComponentFilePaths(componentsDir)).forEach((file) => {
		if (file.includes(".test.") || node_path.default.basename(require_entryPoints.stripAllowedEntryFileExtension(file)) === "index") return;
		const fileName = node_path.default.basename(require_entryPoints.stripAllowedEntryFileExtension(file));
		if (/^[A-Z]/.test(fileName)) {
			nextComponentPaths.set(fileName, file);
			nextKnownComponents.add(fileName);
		}
	});
	return nextComponentPaths;
};
/**
* Analyze an object literal for variant key mappings.
* Handles:
* - Direct property assignments: { fontSize: variant } -> variant maps to fontSize
* - Nullish coalescing: { fontSize: fontSize ?? variant } -> variant maps to fontSize
* - Conditional spreads: ...(condition ? { props } : {}) -> recursively analyze props
*/
const analyzeObjectForVariantMappings = (objLiteral, styleProps, getStylesLiterals, propToVariantKeys, sourceFile) => {
	objLiteral.getProperties().forEach((prop) => {
		if (ts_morph.Node.isPropertyAssignment(prop)) {
			analyzeVariantPropertyAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys);
			return;
		}
		if (ts_morph.Node.isSpreadAssignment(prop)) analyzeVariantSpreadAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
	});
};
const addStyleProp = (styleProps, variantKey) => {
	if (!styleProps.includes(variantKey)) styleProps.push(variantKey);
};
const addPropToVariantKeyMapping = (propToVariantKeys, propName, variantKey) => {
	const existing = propToVariantKeys.get(propName) ?? [];
	if (!existing.includes(variantKey)) propToVariantKeys.set(propName, [...existing, variantKey]);
};
const addRuntimeSelector = (target, key, selector) => {
	const existing = target.get(key) ?? [];
	if (!existing.includes(selector)) target.set(key, [...existing, selector]);
};
const getExpressionWithoutWrappers = (node) => {
	if (ts_morph.Node.isParenthesizedExpression(node)) return getExpressionWithoutWrappers(node.getExpression());
	if (ts_morph.Node.isAsExpression(node) || ts_morph.Node.isTypeAssertion(node) || ts_morph.Node.isSatisfiesExpression(node)) return getExpressionWithoutWrappers(node.getExpression());
	return node;
};
const applyRuntimeSelectorIndex = (selector, indexKey, isIdentifierIndex = false) => {
	if (selector.includes("${")) return selector;
	return isIdentifierIndex ? selector + ".${" + indexKey + "}" : `${selector}.${indexKey}`;
};
const resolveRuntimeBindingFromExpression = (expr, runtimeBindings) => {
	const normalized = getExpressionWithoutWrappers(expr);
	if (ts_morph.Node.isIdentifier(normalized)) return runtimeBindings.get(normalized.getText()) ?? null;
	if (ts_morph.Node.isElementAccessExpression(normalized)) {
		const target = resolveRuntimeBindingFromExpression(normalized.getExpression(), runtimeBindings);
		if (!target) return null;
		const argumentExpression = normalized.getArgumentExpression();
		if (!argumentExpression) return null;
		const argument = getExpressionWithoutWrappers(argumentExpression);
		if (ts_morph.Node.isStringLiteral(argument)) return { selector: applyRuntimeSelectorIndex(target.selector, argument.getLiteralValue()) };
		if (ts_morph.Node.isIdentifier(argument)) return { selector: applyRuntimeSelectorIndex(target.selector, argument.getText(), true) };
	}
	if (ts_morph.Node.isPropertyAccessExpression(normalized)) {
		const target = resolveRuntimeBindingFromExpression(normalized.getExpression(), runtimeBindings);
		if (!target) return null;
		return { selector: applyRuntimeSelectorIndex(target.selector, normalized.getName()) };
	}
	return null;
};
const collectRuntimeSelectorsFromExpression = (expr, runtimeBindings) => {
	const normalized = getExpressionWithoutWrappers(expr);
	const resolvedBinding = resolveRuntimeBindingFromExpression(normalized, runtimeBindings);
	if (resolvedBinding) return [resolvedBinding.selector];
	if (ts_morph.Node.isConditionalExpression(normalized)) return [...collectRuntimeSelectorsFromExpression(normalized.getWhenTrue(), runtimeBindings), ...collectRuntimeSelectorsFromExpression(normalized.getWhenFalse(), runtimeBindings)];
	if (ts_morph.Node.isBinaryExpression(normalized)) return [...collectRuntimeSelectorsFromExpression(normalized.getLeft(), runtimeBindings), ...collectRuntimeSelectorsFromExpression(normalized.getRight(), runtimeBindings)];
	return [];
};
const collectRuntimeConfigBindings = (sourceFile, runtimeBindings, runtimeConfigDefaultProps) => {
	sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).forEach((declaration) => {
		const initializer = declaration.getInitializer();
		if (!initializer) return;
		const normalizedInitializer = getExpressionWithoutWrappers(initializer);
		const nameNode = declaration.getNameNode();
		if (ts_morph.Node.isObjectBindingPattern(nameNode) && ts_morph.Node.isCallExpression(normalizedInitializer)) {
			const hookConfig = require_hookMetadata.getRuntimeHookConfig(normalizedInitializer.getExpression().getText());
			if (!hookConfig) return;
			Object.entries(hookConfig.defaultProps).forEach(([propName, selector]) => {
				runtimeConfigDefaultProps.set(propName, selector);
			});
			nameNode.getElements().forEach((element) => {
				const fieldName = element.getPropertyNameNode()?.getText() ?? element.getName();
				const localName = element.getName();
				const fieldConfig = hookConfig.fields[fieldName];
				if (!fieldConfig) return;
				runtimeBindings.set(localName, { selector: fieldConfig.bindingSelector });
			});
			return;
		}
		if (!ts_morph.Node.isIdentifier(nameNode)) return;
		const resolvedBinding = resolveRuntimeBindingFromExpression(normalizedInitializer, runtimeBindings);
		if (resolvedBinding) runtimeBindings.set(nameNode.getText(), resolvedBinding);
	});
};
const extractFallbackIdentifier = (initializer) => {
	if (!ts_morph.Node.isBinaryExpression(initializer)) return null;
	const operatorKind = initializer.getOperatorToken().getKind();
	if (!(operatorKind === ts_morph.SyntaxKind.QuestionQuestionToken || operatorKind === ts_morph.SyntaxKind.BarBarToken) || !ts_morph.Node.isIdentifier(initializer.getRight())) return null;
	return initializer.getRight().getText();
};
const analyzeVariantPropertyAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys) => {
	const variantKey = prop.getName();
	addStyleProp(styleProps, variantKey);
	const initializer = prop.getInitializer();
	if (!initializer) return;
	if (ts_morph.Node.isStringLiteral(initializer)) getStylesLiterals.set(variantKey, initializer.getLiteralValue());
	if (ts_morph.Node.isIdentifier(initializer)) addPropToVariantKeyMapping(propToVariantKeys, initializer.getText(), variantKey);
	const fallbackIdentifier = extractFallbackIdentifier(initializer);
	if (fallbackIdentifier) addPropToVariantKeyMapping(propToVariantKeys, fallbackIdentifier, variantKey);
};
const findVariableObjectLiteral = (sourceFile, variableName) => {
	const initializer = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).find((candidate) => candidate.getName() === variableName)?.getInitializer();
	return initializer && ts_morph.Node.isObjectLiteralExpression(initializer) ? initializer : null;
};
const analyzeVariantSpreadAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile) => {
	const spreadExpr = prop.getExpression();
	if (ts_morph.Node.isParenthesizedExpression(spreadExpr)) {
		const conditionalExpr = spreadExpr.getExpression();
		if (ts_morph.Node.isConditionalExpression(conditionalExpr)) {
			const whenTrue = conditionalExpr.getWhenTrue();
			if (!ts_morph.Node.isObjectLiteralExpression(whenTrue)) return;
			analyzeObjectForVariantMappings(whenTrue, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
		}
	}
	if (ts_morph.Node.isIdentifier(spreadExpr)) {
		const objectLiteral = findVariableObjectLiteral(sourceFile, spreadExpr.getText());
		if (objectLiteral) analyzeObjectForVariantMappings(objectLiteral, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
	}
};
/**
* Analyzes a UDS component file to extract:
* 1. Default prop values (e.g., display = 'flex')
* 2. Props passed to getStyles()
* 3. Internal UDS component usage
*/
const analyzeComponent = (project, componentPath) => {
	const sourceFile = project.getSourceFile(componentPath);
	if (!sourceFile) return null;
	const componentName = node_path.default.basename(require_entryPoints.stripAllowedEntryFileExtension(componentPath));
	const defaultProps = /* @__PURE__ */ new Map();
	const componentPropNames = /* @__PURE__ */ new Set();
	const styleProps = [];
	const getStylesLiterals = /* @__PURE__ */ new Map();
	const cxLiterals = [];
	const internalComponents = [];
	const internalComponentProps = /* @__PURE__ */ new Map();
	const propToVariantKeys = /* @__PURE__ */ new Map();
	const runtimeConfigDefaultProps = /* @__PURE__ */ new Map();
	const runtimeConfigGetStyles = /* @__PURE__ */ new Map();
	const runtimeConfigInternalComponentProps = /* @__PURE__ */ new Map();
	const runtimeBindings = /* @__PURE__ */ new Map();
	collectComponentDefaultsAndProps(sourceFile, defaultProps, componentPropNames);
	collectRuntimeConfigBindings(sourceFile, runtimeBindings, runtimeConfigDefaultProps);
	collectGetStylesMetadata(sourceFile, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles);
	collectCxLiterals(sourceFile, cxLiterals);
	collectIntrinsicClassNameLiterals(sourceFile, cxLiterals);
	extractInternalComponents(sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentPropNames, runtimeBindings);
	const motionVarPrefixes = extractMotionVarPrefixes(sourceFile);
	if (new Set(["Tab", "TabList"]).has(componentName) && propToVariantKeys.has("variant") && !defaultProps.has("variant")) defaultProps.set("variant", "primary");
	return {
		name: componentName,
		filePath: componentPath,
		defaultProps,
		styleProps,
		getStylesLiterals,
		cxLiterals,
		internalComponents,
		internalComponentProps,
		propToVariantKeys,
		runtimeConfigDefaultProps,
		runtimeConfigGetStyles,
		runtimeConfigInternalComponentProps,
		motionVarPrefixes
	};
};
const getComponentFunctionNodes = (sourceFile) => [...sourceFile.getFunctions(), ...sourceFile.getVariableDeclarations().filter((declaration) => {
	const initializer = declaration.getInitializer();
	return initializer && (ts_morph.Node.isArrowFunction(initializer) || ts_morph.Node.isCallExpression(initializer));
})];
const collectComponentDefaultsAndProps = (sourceFile, defaultProps, componentPropNames) => {
	getComponentFunctionNodes(sourceFile).forEach((fn) => {
		if (ts_morph.Node.isFunctionDeclaration(fn)) {
			extractDefaultsFromFunction(fn, defaultProps);
			extractAllPropNames(fn, componentPropNames);
			return;
		}
		if (!ts_morph.Node.isVariableDeclaration(fn)) return;
		const initializer = fn.getInitializer();
		if (!initializer) return;
		if (ts_morph.Node.isCallExpression(initializer)) initializer.getArguments().forEach((arg) => {
			if (ts_morph.Node.isFunctionExpression(arg) || ts_morph.Node.isArrowFunction(arg)) {
				extractDefaultsFromFunction(arg, defaultProps);
				extractAllPropNames(arg, componentPropNames);
			}
		});
		if (ts_morph.Node.isArrowFunction(initializer)) {
			extractDefaultsFromFunction(initializer, defaultProps);
			extractAllPropNames(initializer, componentPropNames);
		}
	});
};
const extractConditionalStringLiterals = (node) => {
	if (ts_morph.Node.isStringLiteral(node)) return [node.getLiteralValue()];
	if (ts_morph.Node.isConditionalExpression(node)) return [...extractConditionalStringLiterals(node.getWhenTrue()), ...extractConditionalStringLiterals(node.getWhenFalse())];
	return [];
};
const storeVariantLiteralValues = (variantKey, literalValues, getStylesLiterals) => {
	literalValues.forEach((value, index) => {
		const literalKey = index === 0 ? variantKey : `${variantKey}:${index}`;
		getStylesLiterals.set(literalKey, value);
	});
};
/** Values already recorded for `variantKey` (base key plus `variantKey:1`, `:2`, …). */
const getExistingLiteralValuesForVariantKey = (variantKey, getStylesLiterals) => {
	const values = [];
	const base = getStylesLiterals.get(variantKey);
	if (base !== void 0) values.push(base);
	let index = 1;
	while (true) {
		const key = `${variantKey}:${index}`;
		const next = getStylesLiterals.get(key);
		if (next === void 0) break;
		values.push(next);
		index++;
	}
	return values;
};
/**
* Record a string literal for a variant key from a getStyles() call.
* Multiple calls with the same key (e.g. Tab's active-off vs active-on classes) must
* all be kept; a plain Map set would drop earlier literals.
*/
const appendGetStylesStringLiteral = (variantKey, value, getStylesLiterals) => {
	if (getExistingLiteralValuesForVariantKey(variantKey, getStylesLiterals).includes(value)) return;
	let nextIndex = 0;
	while (true) {
		const key = nextIndex === 0 ? variantKey : `${variantKey}:${nextIndex}`;
		if (!getStylesLiterals.has(key)) {
			getStylesLiterals.set(key, value);
			return;
		}
		nextIndex++;
	}
};
const handleGetStylesPropertyAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles) => {
	const variantKey = prop.getName();
	addStyleProp(styleProps, variantKey);
	const initializer = prop.getInitializer();
	if (!initializer) return;
	if (ts_morph.Node.isStringLiteral(initializer)) appendGetStylesStringLiteral(variantKey, initializer.getLiteralValue(), getStylesLiterals);
	if (ts_morph.Node.isIdentifier(initializer)) addPropToVariantKeyMapping(propToVariantKeys, initializer.getText(), variantKey);
	collectRuntimeSelectorsFromExpression(initializer, runtimeBindings).forEach((selector) => {
		addRuntimeSelector(runtimeConfigGetStyles, variantKey, selector);
	});
	const fallbackIdentifier = extractFallbackIdentifier(initializer);
	if (fallbackIdentifier) addPropToVariantKeyMapping(propToVariantKeys, fallbackIdentifier, variantKey);
	if (ts_morph.Node.isConditionalExpression(initializer)) storeVariantLiteralValues(variantKey, [...extractConditionalStringLiterals(initializer.getWhenTrue()), ...extractConditionalStringLiterals(initializer.getWhenFalse())], getStylesLiterals);
};
const handleGetStylesObjectProperty = (prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile, runtimeBindings, runtimeConfigGetStyles) => {
	if (ts_morph.Node.isPropertyAssignment(prop)) {
		handleGetStylesPropertyAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles);
		return;
	}
	if (ts_morph.Node.isShorthandPropertyAssignment(prop)) {
		addStyleProp(styleProps, prop.getName());
		return;
	}
	if (ts_morph.Node.isSpreadAssignment(prop) && ts_morph.Node.isIdentifier(prop.getExpression())) {
		const objectLiteral = findVariableObjectLiteral(sourceFile, prop.getExpression().getText());
		if (objectLiteral) analyzeObjectForVariantMappings(objectLiteral, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
	}
};
const collectGetStylesMetadata = (sourceFile, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles) => {
	sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "getStyles").forEach((call) => {
		const args = call.getArguments();
		if (args.length === 0 || !ts_morph.Node.isObjectLiteralExpression(args[0])) return;
		args[0].getProperties().forEach((prop) => {
			handleGetStylesObjectProperty(prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile, runtimeBindings, runtimeConfigGetStyles);
		});
	});
};
const collectCxLiterals = (sourceFile, cxLiterals) => {
	sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "cx").forEach((call) => {
		call.getArguments().forEach((arg) => extractCxStringLiterals(arg, cxLiterals));
	});
};
const pushUniqueClasses = (target, rawValue) => {
	rawValue.split(/\s+/).filter(Boolean).forEach((className) => {
		if (!target.includes(className)) target.push(className);
	});
};
const collectIntrinsicClassNameLiterals = (sourceFile, cxLiterals) => {
	[...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)].forEach((element) => {
		const tagName = element.getTagNameNode().getText();
		if (!/^[a-z]/.test(tagName)) return;
		element.getAttributes().forEach((attr) => {
			if (!ts_morph.Node.isJsxAttribute(attr) || attr.getNameNode().getText() !== "className") return;
			const initializer = attr.getInitializer();
			if (!initializer) return;
			if (ts_morph.Node.isStringLiteral(initializer)) {
				pushUniqueClasses(cxLiterals, initializer.getLiteralValue());
				return;
			}
			if (!ts_morph.Node.isJsxExpression(initializer)) return;
			const expr = initializer.getExpression();
			if (expr && ts_morph.Node.isStringLiteral(expr)) pushUniqueClasses(cxLiterals, expr.getLiteralValue());
		});
	});
};
/**
* Extract UDS components used internally in the file and their prop values.
* Also detects prop aliasing (e.g., columnGap={gap} means gap -> columnGap).
*/
const extractInternalComponents = (sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentProps, runtimeBindings) => {
	collectImportedInternalComponents(sourceFile, internalComponents);
	collectInternalComponentUsages(sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentProps, runtimeBindings);
};
const isInternalUdsModule = (moduleSpec) => {
	return (moduleSpec.startsWith("@yahoo/uds") || moduleSpec.startsWith("../") || moduleSpec.startsWith("./")) && (moduleSpec.includes("/components/") || moduleSpec === "@yahoo/uds");
};
const pushUniqueComponentName = (components, name) => {
	if (/^[A-Z]/.test(name) && !components.includes(name)) components.push(name);
};
const collectImportedInternalComponents = (sourceFile, internalComponents) => {
	sourceFile.getImportDeclarations().forEach((importDecl) => {
		if (!isInternalUdsModule(importDecl.getModuleSpecifierValue())) return;
		importDecl.getNamedImports().forEach((namedImport) => pushUniqueComponentName(internalComponents, namedImport.getName()));
	});
};
const getOrCreateComponentPropsMap = (internalComponentProps, componentName) => {
	const existing = internalComponentProps.get(componentName);
	if (existing) return existing;
	const created = /* @__PURE__ */ new Map();
	internalComponentProps.set(componentName, created);
	return created;
};
const extractJsxAttributeLiteralValues = (attr, componentProps, propToVariantKeys) => {
	if (!ts_morph.Node.isJsxAttribute(attr)) return null;
	const propName = attr.getNameNode().getText();
	const initializer = attr.getInitializer();
	if (!initializer) return {
		propName,
		values: []
	};
	if (ts_morph.Node.isStringLiteral(initializer)) return {
		propName,
		values: [initializer.getLiteralValue()]
	};
	if (!ts_morph.Node.isJsxExpression(initializer)) return {
		propName,
		values: []
	};
	const expr = initializer.getExpression();
	if (expr && ts_morph.Node.isStringLiteral(expr)) return {
		propName,
		values: [expr.getLiteralValue()]
	};
	if (expr && ts_morph.Node.isIdentifier(expr)) {
		const identifierName = expr.getText();
		if (componentProps.has(identifierName) && identifierName !== propName) addPropToVariantKeyMapping(propToVariantKeys, identifierName, propName);
	}
	return {
		propName,
		values: []
	};
};
const collectInternalComponentUsages = (sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentProps, runtimeBindings) => {
	[...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)].forEach((element) => {
		const tagName = element.getTagNameNode().getText();
		if (!/^[A-Z]/.test(tagName)) return;
		pushUniqueComponentName(internalComponents, tagName);
		element.getAttributes().forEach((attr) => {
			if (ts_morph.Node.isJsxAttribute(attr)) {
				const initializer = attr.getInitializer();
				const expression = initializer && ts_morph.Node.isJsxExpression(initializer) ? initializer.getExpression() : void 0;
				const runtimeSelectors = expression ? collectRuntimeSelectorsFromExpression(expression, runtimeBindings) : [];
				if (runtimeSelectors.length > 0) {
					const runtimePropsMap = getOrCreateComponentPropsMap(runtimeConfigInternalComponentProps, tagName);
					const runtimePropName = attr.getNameNode().getText();
					const existingRuntimeSelectors = runtimePropsMap.get(runtimePropName) ?? [];
					runtimePropsMap.set(runtimePropName, [...new Set([...existingRuntimeSelectors, ...runtimeSelectors])]);
				}
			}
			const extracted = extractJsxAttributeLiteralValues(attr, componentProps, propToVariantKeys);
			if (!extracted || extracted.values.length === 0) return;
			const componentPropsMap = getOrCreateComponentPropsMap(internalComponentProps, tagName);
			const existingValues = componentPropsMap.get(extracted.propName) ?? [];
			const mergedValues = [...new Set([...existingValues, ...extracted.values])];
			componentPropsMap.set(extracted.propName, mergedValues);
		});
	});
};
/**
* Extract default prop values from a function's parameter destructuring
*/
const extractDefaultsFromFunction = (fn, defaults) => {
	let params = [];
	if (ts_morph.Node.isFunctionDeclaration(fn) || ts_morph.Node.isFunctionExpression(fn)) params = fn.getParameters();
	else if (ts_morph.Node.isArrowFunction(fn)) params = fn.getParameters();
	params.forEach((param) => {
		if (!ts_morph.Node.isParameterDeclaration(param)) return;
		const nameNode = param.getNameNode();
		if (!nameNode || !ts_morph.Node.isObjectBindingPattern(nameNode)) return;
		nameNode.getElements().forEach((element) => {
			const propName = element.getPropertyNameNode()?.getText() || element.getName();
			const initializer = element.getInitializer();
			if (initializer && ts_morph.Node.isStringLiteral(initializer)) defaults.set(propName, initializer.getLiteralValue());
			else if (initializer && ts_morph.Node.isIdentifier(initializer)) {
				const resolved = resolveIdentifierToStringLiteral(initializer);
				if (resolved) defaults.set(propName, resolved);
			}
		});
	});
};
/**
* Extract ALL prop names from a function's parameter destructuring (not just defaults)
*/
const extractAllPropNames = (fn, propNames) => {
	let params = [];
	if (ts_morph.Node.isFunctionDeclaration(fn) || ts_morph.Node.isFunctionExpression(fn)) params = fn.getParameters();
	else if (ts_morph.Node.isArrowFunction(fn)) params = fn.getParameters();
	params.forEach((param) => {
		if (!ts_morph.Node.isParameterDeclaration(param)) return;
		const nameNode = param.getNameNode();
		if (!nameNode || !ts_morph.Node.isObjectBindingPattern(nameNode)) return;
		nameNode.getElements().forEach((element) => {
			const propName = element.getPropertyNameNode()?.getText() || element.getName();
			propNames.add(propName);
		});
	});
};
/**
* Extract string literals from cx() call arguments.
* Handles:
* - Direct string literals: cx('class1', 'class2')
* - Object keys: cx({ 'class1': condition, 'class2': true })
* - Nested calls and arrays
*/
const extractCxStringLiterals = (node, literals) => {
	if (ts_morph.Node.isStringLiteral(node)) node.getLiteralValue().split(/\s+/).filter(Boolean).forEach((cls) => {
		if (!literals.includes(cls)) literals.push(cls);
	});
	else if (ts_morph.Node.isObjectLiteralExpression(node)) node.getProperties().forEach((prop) => {
		if (ts_morph.Node.isPropertyAssignment(prop)) {
			const nameNode = prop.getNameNode();
			if (ts_morph.Node.isStringLiteral(nameNode)) nameNode.getLiteralValue().split(/\s+/).filter(Boolean).forEach((cls) => {
				if (!literals.includes(cls)) literals.push(cls);
			});
			else if (ts_morph.Node.isIdentifier(nameNode)) {
				const cls = nameNode.getText();
				if (!literals.includes(cls)) literals.push(cls);
			}
		}
	});
	else if (ts_morph.Node.isArrayLiteralExpression(node)) node.getElements().forEach((element) => {
		extractCxStringLiterals(element, literals);
	});
	else if (ts_morph.Node.isConditionalExpression(node)) {
		extractCxStringLiterals(node.getWhenTrue(), literals);
		extractCxStringLiterals(node.getWhenFalse(), literals);
	} else if (ts_morph.Node.isBinaryExpression(node)) {
		extractCxStringLiterals(node.getLeft(), literals);
		extractCxStringLiterals(node.getRight(), literals);
	}
};
/**
* Try to resolve an identifier to its initializer value (for const declarations)
*/
const resolveIdentifierToObject = (sourceFile, identifier) => {
	const decl = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).find((candidate) => candidate.getName() === identifier);
	if (!decl) return null;
	let initializer = decl.getInitializer();
	if (!initializer) return null;
	if (ts_morph.Node.isAsExpression(initializer)) initializer = initializer.getExpression();
	if (!ts_morph.Node.isObjectLiteralExpression(initializer)) return null;
	const result = {};
	initializer.getProperties().forEach((prop) => {
		if (!ts_morph.Node.isPropertyAssignment(prop)) return;
		const propName = prop.getName();
		const propInit = prop.getInitializer();
		if (propInit && ts_morph.Node.isStringLiteral(propInit)) result[propName] = propInit.getLiteralValue();
	});
	return result;
};
/**
* Extract motion CSS variable prefixes from SpringMotionConfig usage.
* Returns prefixes like ['--uds-motion-bouncy-4-', '--uds-motion-smooth-3-']
*/
const extractMotionVarPrefixes = (sourceFile) => {
	const prefixes = [];
	[...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)].forEach((element) => {
		if (element.getTagNameNode().getText() !== "SpringMotionConfig") return;
		const props = {
			layoutVariant: null,
			layoutSpeed: null,
			colorVariant: null,
			colorSpeed: null
		};
		element.getAttributes().forEach((attr) => {
			if (ts_morph.Node.isJsxSpreadAttribute(attr)) {
				const expr = attr.getExpression();
				if (ts_morph.Node.isIdentifier(expr)) {
					const spreadObj = resolveIdentifierToObject(sourceFile, expr.getText());
					if (spreadObj) Object.keys(props).forEach((key) => {
						if (key in spreadObj) props[key] = spreadObj[key];
					});
				}
				return;
			}
			if (!ts_morph.Node.isJsxAttribute(attr)) return;
			const propName = attr.getNameNode().getText();
			if (!(propName in props)) return;
			const initializer = attr.getInitializer();
			if (initializer) {
				if (ts_morph.Node.isStringLiteral(initializer)) props[propName] = initializer.getLiteralValue();
				else if (ts_morph.Node.isJsxExpression(initializer)) {
					const expr = initializer.getExpression();
					if (expr && ts_morph.Node.isStringLiteral(expr)) props[propName] = expr.getLiteralValue();
				}
			}
		});
		const layoutPrefix = `--uds-motion-${props.layoutVariant ?? require_index.SPRING_MOTION_DEFAULTS.layoutVariant}-${props.layoutSpeed ?? require_index.SPRING_MOTION_DEFAULTS.layoutSpeed}-`;
		if (!prefixes.includes(layoutPrefix)) prefixes.push(layoutPrefix);
		const colorPrefix = `--uds-motion-${props.colorVariant ?? require_index.SPRING_MOTION_DEFAULTS.colorVariant}-${props.colorSpeed ?? require_index.SPRING_MOTION_DEFAULTS.colorSpeed}-`;
		if (!prefixes.includes(colorPrefix)) prefixes.push(colorPrefix);
	});
	return prefixes;
};
const resolveIdentifierToStringLiteral = (identifier) => {
	if (!ts_morph.Node.isIdentifier(identifier)) return null;
	const symbol = identifier.getSymbol();
	if (!symbol) return resolveImportedIdentifier(identifier);
	const resolvedDeclarationValue = symbol.getDeclarations().reduce((resolved, declaration) => {
		if (resolved) return resolved;
		if (ts_morph.Node.isVariableDeclaration(declaration)) {
			let initializer = declaration.getInitializer();
			if (initializer && ts_morph.Node.isAsExpression(initializer)) initializer = initializer.getExpression();
			if (initializer && ts_morph.Node.isStringLiteral(initializer)) return initializer.getLiteralValue();
		}
		if (ts_morph.Node.isEnumMember(declaration)) {
			const initializer = declaration.getInitializer();
			if (initializer && ts_morph.Node.isStringLiteral(initializer)) return initializer.getLiteralValue();
		}
	}, void 0);
	if (resolvedDeclarationValue) return resolvedDeclarationValue;
	return resolveImportedIdentifier(identifier);
};
const resolveImportedIdentifier = (identifier) => {
	if (!ts_morph.Node.isIdentifier(identifier)) return null;
	const name = identifier.getText();
	const sourceFile = identifier.getSourceFile();
	const project = sourceFile.getProject();
	const baseDir = node_path.default.dirname(sourceFile.getFilePath());
	const importResolution = sourceFile.getImportDeclarations().reduce((resolvedImport, importDecl) => {
		if (resolvedImport) return resolvedImport;
		if (!importDecl.getNamedImports().find((n) => n.getName() === name)) return;
		const moduleSpec = importDecl.getModuleSpecifierValue();
		if (!moduleSpec.startsWith(".") || hasImportQuery(moduleSpec)) return;
		const resolvedBase = node_path.default.resolve(baseDir, moduleSpec);
		return [
			resolvedBase,
			`${resolvedBase}.ts`,
			`${resolvedBase}.tsx`
		].reduce((resolvedCandidate, candidate) => {
			if (resolvedCandidate) return resolvedCandidate;
			if (!(0, node_fs.existsSync)(candidate)) return;
			const importedFile = project.addSourceFileAtPathIfExists(candidate);
			if (!importedFile) return;
			const varDecl = importedFile.getVariableDeclaration(name);
			if (!varDecl) return;
			let initializer = varDecl.getInitializer();
			if (initializer && ts_morph.Node.isAsExpression(initializer)) initializer = initializer.getExpression();
			return initializer && ts_morph.Node.isStringLiteral(initializer) ? initializer.getLiteralValue() : void 0;
		}, void 0);
	}, void 0);
	if (importResolution) return importResolution;
	return null;
};
//#endregion
exports.analyzeComponent = analyzeComponent;
exports.scanComponentFiles = scanComponentFiles;
