import { CredentialResolver, init_credentials } from "../../../../auth/credentials.js";
import { BindingsConfigSchema, McpConfigSchema, init_schema } from "../../../../config/schema.js";
import { canonicalizeConfiguredMcpServer } from "../../../../config/mcp-config-normalize.js";
import { mergeCronConfigPatch, mergeGatewaySkillsMarketplacePatch, mergeGoalsConfigPatch, mergeSessionConfigPatch, mergeUpdateConfigPatch } from "../../../../config/web-patch.js";
import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../../../auth.js";
import { isMaskedSecretPatchValue } from "../../lib/mask-secret-length.js";
import { applyToolsWebPatch } from "../../../config-tools-web.js";
import { mergeTunnelConfigPatch } from "../../../../tunnel/tunnel-config.js";
import { assertGatewayRuntimeConfig } from "../../../runtime-config.js";
import { mergeSttConfigPatch, mergeTtsConfigPatch } from "../../lib/safe-voice-config.js";
import { PATCH_OK, patchError } from "./result.js";
//#region src/gateway/hono/routes/config-patch/misc.ts
init_schema();
init_credentials();
async function applyMiscPatch(config, body) {
	if (body.update !== void 0 && typeof body.update === "object" && body.update !== null) {
		const updateResult = mergeUpdateConfigPatch(config, body.update);
		if (updateResult.ok === false) return patchError(updateResult.message);
	}
	if (body.cron !== void 0) {
		if (typeof body.cron !== "object" || body.cron === null || Array.isArray(body.cron)) return patchError("cron must be an object");
		const cronResult = mergeCronConfigPatch(config, body.cron);
		if (cronResult.ok === false) return patchError(cronResult.message);
	}
	if (body.goals !== void 0) {
		if (typeof body.goals !== "object" || body.goals === null || Array.isArray(body.goals)) return patchError("goals must be an object");
		const goalsResult = mergeGoalsConfigPatch(config, body.goals);
		if (goalsResult.ok === false) return patchError(goalsResult.message);
	}
	if (body.session !== void 0) {
		if (typeof body.session !== "object" || body.session === null || Array.isArray(body.session)) return patchError("session must be an object");
		const sessionResult = mergeSessionConfigPatch(config, body.session);
		if (sessionResult.ok === false) return patchError(sessionResult.message);
	}
	if (body.gateway !== void 0 && typeof body.gateway === "object" && body.gateway !== null && !Array.isArray(body.gateway)) {
		const gwPatch = body.gateway;
		if (gwPatch.skillsMarketplaceProvider !== void 0 || gwPatch.skillsStoreBaseUrl !== void 0) {
			const skillsResult = mergeGatewaySkillsMarketplacePatch(config, {
				...gwPatch.skillsMarketplaceProvider !== void 0 ? { skillsMarketplaceProvider: gwPatch.skillsMarketplaceProvider } : {},
				...gwPatch.skillsStoreBaseUrl !== void 0 ? { skillsStoreBaseUrl: gwPatch.skillsStoreBaseUrl } : {}
			});
			if (skillsResult.ok === false) return patchError(skillsResult.message);
		}
	}
	if (body.providers) {
		const resolver = new CredentialResolver();
		for (const [key, apiKey] of Object.entries(body.providers)) if (apiKey !== void 0 && typeof apiKey === "string" && apiKey.trim() && !isMaskedSecretPatchValue(apiKey)) await resolver.saveApiKey(key, apiKey, { profileName: "default" });
	}
	if (body.providersConfig && typeof body.providersConfig === "object" && !Array.isArray(body.providersConfig)) {
		const cfgProviders = config.providers ?? {};
		for (const [vendorId, raw] of Object.entries(body.providersConfig)) {
			if (!vendorId || typeof vendorId !== "string") continue;
			if (raw === null) {
				delete cfgProviders[vendorId];
				continue;
			}
			if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
			const next = cfgProviders[vendorId] ?? {};
			const patch = raw;
			for (const field of [
				"apiKey",
				"baseUrl",
				"region",
				"imageBaseUrl"
			]) if (patch[field] === null || patch[field] === "") delete next[field];
			else if (typeof patch[field] === "string") {
				const trimmed = patch[field].trim();
				if (field === "apiKey" && isMaskedSecretPatchValue(trimmed)) continue;
				next[field] = trimmed;
			}
			if (patch.azure === null) delete next.azure;
			else if (patch.azure && typeof patch.azure === "object" && !Array.isArray(patch.azure)) next.azure = {
				...next.azure ?? {},
				...patch.azure
			};
			if (patch.request === null) delete next.request;
			else if (patch.request && typeof patch.request === "object" && !Array.isArray(patch.request)) next.request = {
				...next.request ?? {},
				...patch.request
			};
			cfgProviders[vendorId] = next;
		}
		config.providers = cfgProviders;
	}
	if (body.stt !== void 0) {
		config.tools = config.tools ?? {};
		config.tools.media = config.tools.media ?? {};
		config.tools.media.audio = mergeSttConfigPatch(config.tools.media.audio, body.stt);
	}
	if (body.tts !== void 0) {
		config.messages = config.messages ?? {};
		config.messages.tts = mergeTtsConfigPatch(config.messages.tts, body.tts);
	}
	const toolsPatchErr = applyToolsWebPatch(config, body);
	if (toolsPatchErr) return patchError(toolsPatchErr);
	if (body.tunnel !== void 0) {
		if (!body.tunnel || typeof body.tunnel !== "object" || Array.isArray(body.tunnel)) return patchError("tunnel must be an object");
		const tunnelResult = mergeTunnelConfigPatch(config, body.tunnel);
		if (tunnelResult.ok === false) return patchError(tunnelResult.message);
	}
	if (body.bindings !== void 0) {
		if (!Array.isArray(body.bindings)) return patchError("bindings must be an array");
		const parsed = BindingsConfigSchema.safeParse(body.bindings);
		if (!parsed.success) return patchError(parsed.error.issues.map((i) => i.message).join("; "));
		config.bindings = parsed.data;
	}
	if (body.mcp !== void 0) if (body.mcp === null) delete config.mcp;
	else if (typeof body.mcp !== "object" || Array.isArray(body.mcp)) return patchError("mcp must be an object");
	else {
		const parsed = McpConfigSchema.safeParse(body.mcp);
		if (!parsed.success) return patchError(parsed.error.issues.map((i) => i.message).join("; "));
		if (parsed.data === void 0) delete config.mcp;
		else {
			const next = { ...parsed.data };
			if (next.servers) next.servers = Object.fromEntries(Object.entries(next.servers).map(([name, server]) => [name, canonicalizeConfiguredMcpServer(server)]));
			config.mcp = next;
		}
	}
	return PATCH_OK;
}
/**
* Re-validate gateway runtime config when `body.gateway` touched anything that
* could break the bind/auth contract. Runs *after* all per-section patches
* land so it sees the fully merged shape.
*/
function validateGatewayAfterPatch(config, body) {
	if (body.gateway === void 0) return PATCH_OK;
	try {
		const auth = resolveGatewayAuth({ authConfig: config.gateway?.auth });
		assertGatewayAuthConfigured(auth);
		assertGatewayRuntimeConfig({
			cfg: config,
			auth,
			port: config.gateway?.port ?? 18790
		});
	} catch (err) {
		return patchError(err instanceof Error ? err.message : String(err));
	}
	return PATCH_OK;
}
//#endregion
export { applyMiscPatch, validateGatewayAfterPatch };

//# sourceMappingURL=misc.js.map