/**
 * model-route-snapshot.js - secret-safe model route snapshots.
 *
 * Purpose: keep Droid's useful runtime model reproducibility evidence while
 * guaranteeing API keys, tokens, and headers are never persisted in SF state.
 *
 * Consumer: UOK audit/progress projections and future run-state snapshots that
 * need provider/model evidence without copying credentials.
 */

const SECRET_KEYS = new Set([
	"apiKey",
	"api_key",
	"authorization",
	"authHeader",
	"headers",
	"token",
	"secret",
	"password",
]);

function stringOrNull(value) {
	return typeof value === "string" && value.trim().length > 0
		? value.trim()
		: null;
}

function maybeRedacted(value, key) {
	if (SECRET_KEYS.has(key)) return "[REDACTED]";
	return value;
}

/**
 * Build a secret-safe snapshot of one resolved model route.
 *
 * Purpose: record what SF actually routed to while keeping durable evidence
 * separate from BYOK credentials and provider secrets.
 *
 * Consumer: model route evidence emitters and run-state projection writers.
 */
export function sanitizeModelRouteSnapshot(route = {}) {
	const source = route && typeof route === "object" ? route : {};
	return {
		provider: stringOrNull(source.provider),
		model: stringOrNull(source.id ?? source.model ?? source.modelId),
		displayName: stringOrNull(source.displayName),
		api: stringOrNull(source.api),
		authMode: stringOrNull(source.authMode),
		baseUrl: stringOrNull(source.baseUrl),
		isCustom: Boolean(source.isCustom ?? source.custom),
		byok: source.authMode === "apiKey" || Boolean(source.byok),
		noImageSupport: Boolean(source.noImageSupport),
	};
}

/**
 * Redact a provider/model configuration object while preserving non-secret
 * route metadata.
 *
 * Purpose: make tests and projections fail closed if a caller accidentally
 * passes Droid-style custom model config containing raw credentials.
 *
 * Consumer: snapshot writers before serializing model/provider config evidence.
 */
export function redactModelConfigSecrets(config = {}) {
	if (!config || typeof config !== "object" || Array.isArray(config)) return {};
	const redacted = {};
	for (const [key, value] of Object.entries(config)) {
		redacted[key] = maybeRedacted(value, key);
	}
	return redacted;
}

/**
 * Build a secret-safe snapshot for a route plus optional routing evidence.
 *
 * Purpose: capture enough model evidence to debug auto routing decisions
 * without making concrete model IDs durable policy or leaking BYOK secrets.
 *
 * Consumer: UOK model routing events and future run-state projections.
 */
export function buildModelRouteSnapshot(args = {}) {
	const route = sanitizeModelRouteSnapshot(args.route ?? args.model ?? {});
	return {
		schemaVersion: 1,
		role: stringOrNull(args.role),
		unitType: stringOrNull(args.unitType),
		unitId: stringOrNull(args.unitId),
		requestedPolicy: args.requestedPolicy ?? { mode: "auto", constraints: [] },
		route,
		routingReason: stringOrNull(args.routingReason),
		fallbacksTried: Array.isArray(args.fallbacksTried)
			? args.fallbacksTried.map(sanitizeModelRouteSnapshot)
			: [],
		configEvidence: redactModelConfigSecrets(args.configEvidence ?? {}),
	};
}
