import { getExample } from "./get-example.js";
import { deSerializeParameter } from "./de-serialize-parameter.js";
import { isParamDisabled } from "../../request-block/helpers/is-param-disabled.js";
import { serializeContentValue, serializeDeepObjectStyle, serializeFormStyle, serializeFormStyleForCookies, serializePipeDelimitedStyle, serializeSimpleStyle, serializeSpaceDelimitedStyle } from "./serialize-parameter.js";
import { isDefined } from "@scalar/helpers/array/is-defined";
import { replaceEnvVariables } from "@scalar/helpers/regex/replace-variables";
import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
import { xScalarCookieSchema } from "@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies";
import { coerceValue } from "@scalar/workspace-store/schemas/typebox-coerce";
import { isObject } from "@scalar/helpers/object/is-object";
//#region src/v2/blocks/operation-block/helpers/build-request-parameters.ts
/** Helper to get explode value with default */
var getExplode = (param, defaultValue) => "explode" in param && param.explode !== void 0 ? param.explode : defaultValue;
/**
* Converts the parameters into a set of headers, cookies and url params while
* replacing environment variables and extracting example values. Also builds up a record of the path
* parameters which can then be used to replace variables in the path.
* Also handles both content based and schema based parameters.
*
* @param parameters - Unfiltered parameters
* @param env - Environment variables flattened into a key-value object
* @param exampleKey - The key of the current example
* @returns A set of headers, cookies and url params
*/
var buildRequestParameters = (parameters = [], env = {}, exampleKey = "default") => {
	const result = {
		cookies: [],
		headers: {},
		pathVariables: {},
		allowReservedQueryParameters: /* @__PURE__ */ new Set(),
		urlParams: new URLSearchParams()
	};
	if (parameters.length === 0) return result;
	for (const referencedParam of parameters) {
		const param = getResolvedRef(referencedParam);
		const example = getExample(param, exampleKey, void 0);
		if (!example || isParamDisabled(param, example)) continue;
		/** De-serialize the example value if it is a string and matches the schema type */
		const deSerializedValue = deSerializeParameter(typeof example.value === "string" ? replaceEnvVariables(example.value, env) : example.value, param);
		const paramName = replaceEnvVariables(param.name, env);
		switch (param.in) {
			case "header": {
				if (paramName.toLowerCase() === "content-type" && deSerializedValue === "multipart/form-data") break;
				/** Headers only support simple style according to OpenAPI 3.1.1 */
				const serialized = serializeSimpleStyle(deSerializedValue, getExplode(param, false));
				if (!isDefined(serialized)) break;
				/** Headers can only be strings so we can cast numbers etc */
				const serializedString = String(serialized);
				if (result.headers[paramName]) result.headers[paramName] = `${result.headers[paramName]},${serializedString}`;
				else result.headers[paramName] = serializedString;
				break;
			}
			case "path": {
				const serialized = serializeSimpleStyle(deSerializedValue, getExplode(param, false));
				result.pathVariables[paramName] = encodeURIComponent(String(serialized));
				break;
			}
			case "query":
				processQueryParameter(param, paramName, deSerializedValue, result.urlParams, result.allowReservedQueryParameters);
				break;
			case "cookie":
				processCookieParameter(paramName, deSerializedValue, getExplode(param, true), result.cookies);
				break;
		}
	}
	return result;
};
/** Ensure we only apply the correcet style to the correct types */
var getStyle = (param, replacedValue) => {
	if (!("style" in param) || !param.style) return "form";
	if (param.style === "deepObject") {
		if (isObject(replacedValue)) return "deepObject";
		return "form";
	}
	return param.style;
};
/** Whether the parameter allows reserved characters (from param or schema). */
var isAllowReserved = (param) => {
	if ("allowReserved" in param && param.allowReserved !== void 0) return param.allowReserved;
	if ("schema" in param && param.schema && typeof param.schema === "object" && "allowReserved" in param.schema) return param.schema.allowReserved === true;
	return false;
};
/** When allowReserved is true, add keys to the set so reserved chars stay unescaped in the URL. */
var trackReservedKeys = (allowReservedQueryParameters, allowReserved, ...keys) => {
	if (allowReserved) for (const key of keys) allowReservedQueryParameters.add(key);
};
/**
* Helper function to process query parameters.
* Extracted to reduce complexity in main function.
*/
var processQueryParameter = (param, paramName, replacedValue, urlParams, allowReservedQueryParameters) => {
	/** If the parameter should be exploded, defaults to true for form style */
	const explodeParam = "explode" in param && param.explode !== void 0 ? param.explode : true;
	const allowReserved = isAllowReserved(param);
	/** Style of the parameter, defaults to form */
	const style = getStyle(param, replacedValue);
	if ("content" in param && param.content) {
		const serializedValue = serializeContentValue(replacedValue, Object.keys(param.content)[0] ?? "application/json");
		urlParams.set(paramName, serializedValue);
		trackReservedKeys(allowReservedQueryParameters, allowReserved, paramName);
		return;
	}
	if (style === "deepObject" && explodeParam) {
		const entries = serializeDeepObjectStyle(paramName, replacedValue);
		for (const entry of entries) {
			urlParams.append(entry.key, entry.value);
			trackReservedKeys(allowReservedQueryParameters, allowReserved, entry.key);
		}
		return;
	}
	if (style === "spaceDelimited") {
		const serialized = serializeSpaceDelimitedStyle(replacedValue);
		const existingValue = urlParams.get(paramName);
		urlParams.set(paramName, existingValue ? `${existingValue} ${serialized}` : serialized);
		trackReservedKeys(allowReservedQueryParameters, allowReserved, paramName);
		return;
	}
	if (style === "pipeDelimited") {
		const serialized = serializePipeDelimitedStyle(replacedValue);
		const existingValue = urlParams.get(paramName);
		urlParams.set(paramName, existingValue ? `${existingValue}|${serialized}` : serialized);
		trackReservedKeys(allowReservedQueryParameters, allowReserved, paramName);
		return;
	}
	const serialized = serializeFormStyle(replacedValue, explodeParam);
	if (Array.isArray(serialized)) for (const entry of serialized) {
		const key = entry.key || paramName;
		urlParams.append(key, String(entry.value));
		trackReservedKeys(allowReservedQueryParameters, allowReserved, key);
	}
	else {
		urlParams.append(paramName, String(serialized));
		trackReservedKeys(allowReservedQueryParameters, allowReserved, paramName);
	}
};
/**
* Helper function to process cookie parameters.
* Extracted to reduce complexity in main function.
*/
var processCookieParameter = (paramName, replacedValue, explode, cookies) => {
	const serialized = serializeFormStyleForCookies(replacedValue, explode);
	if (Array.isArray(serialized)) for (const entry of serialized) {
		const key = entry.key || paramName;
		cookies.push(coerceValue(xScalarCookieSchema, {
			name: key,
			value: String(entry.value),
			path: "/"
		}));
	}
	else cookies.push(coerceValue(xScalarCookieSchema, {
		name: paramName,
		value: String(serialized),
		path: "/"
	}));
};
//#endregion
export { buildRequestParameters };

//# sourceMappingURL=build-request-parameters.js.map