import { DEFAULT_TOOL_PLACEMENT } from "./tool-config-defaults.js";
const DEFAULT_PLACEMENT = {
    section: [...DEFAULT_TOOL_PLACEMENT.section],
    item: [...DEFAULT_TOOL_PLACEMENT.item],
    passage: [...DEFAULT_TOOL_PLACEMENT.passage],
};
function isPlainObject(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
}
function assertStringArray(value, fieldPath) {
    if (value == null)
        return [];
    if (!Array.isArray(value)) {
        throw new Error(`Invalid tools config at "${fieldPath}": expected an array of tool ids.`);
    }
    const invalidEntry = value.find((entry) => typeof entry !== "string");
    if (invalidEntry !== undefined) {
        throw new Error(`Invalid tools config at "${fieldPath}": all entries must be strings.`);
    }
    return value;
}
function assertPlacementConfig(value) {
    if (value == null)
        return undefined;
    if (!isPlainObject(value)) {
        throw new Error('Invalid tools config at "placement": expected an object with section/item/passage arrays.');
    }
    return value;
}
function assertPolicyConfig(value) {
    if (value == null)
        return undefined;
    if (!isPlainObject(value)) {
        throw new Error('Invalid tools config at "policy": expected an object with allowed/blocked arrays.');
    }
    return value;
}
function assertProviderConfig(providerId, value) {
    if (value == null)
        return undefined;
    if (!isPlainObject(value)) {
        throw new Error(`Invalid tools config at "providers.${providerId}": expected an object.`);
    }
    const config = value;
    const isTTSRuntimeProviderId = (provider) => provider === "polly" || provider === "google" || provider === "custom";
    if ("enabled" in config &&
        config.enabled !== undefined &&
        typeof config.enabled !== "boolean") {
        throw new Error(`Invalid tools config at "providers.${providerId}.enabled": expected a boolean.`);
    }
    if ("settings" in config &&
        config.settings !== undefined &&
        !isPlainObject(config.settings)) {
        throw new Error(`Invalid tools config at "providers.${providerId}.settings": expected an object.`);
    }
    if ("provider" in config &&
        config.provider !== undefined &&
        !isPlainObject(config.provider) &&
        !(providerId === "textToSpeech" && isTTSRuntimeProviderId(config.provider))) {
        throw new Error(`Invalid tools config at "providers.${providerId}.provider": expected an object.`);
    }
    return config;
}
function assertProvidersConfig(value) {
    if (value == null)
        return {};
    if (!isPlainObject(value)) {
        throw new Error('Invalid tools config at "providers": expected an object keyed by tool id.');
    }
    const normalized = {};
    for (const [providerId, providerConfig] of Object.entries(value)) {
        normalized[providerId] = assertProviderConfig(providerId, providerConfig);
    }
    return normalized;
}
export function normalizeToolAlias(toolId) {
    const trimmed = toolId.trim();
    if (!trimmed)
        return "";
    return trimmed;
}
export function normalizeToolList(toolIds) {
    if (!toolIds || toolIds.length === 0)
        return [];
    const deduped = new Set();
    for (const rawToolId of toolIds) {
        if (typeof rawToolId !== "string") {
            throw new Error("Invalid tools config: tool list entries must be strings.");
        }
        const normalized = normalizeToolAlias(rawToolId);
        if (!normalized)
            continue;
        deduped.add(normalized);
    }
    return Array.from(deduped);
}
export function parseToolList(input) {
    if (!input)
        return [];
    return normalizeToolList(input
        .split(",")
        .map((entry) => entry.trim())
        .filter(Boolean));
}
function assertPnpEnforcement(value, fieldPath) {
    if (value == null)
        return undefined;
    if (value === "on" || value === "off")
        return value;
    throw new Error(`Invalid tools config at "${fieldPath}": expected "on" or "off", got ${JSON.stringify(value)}.`);
}
export function normalizeToolsConfig(input) {
    if (input != null && !isPlainObject(input)) {
        throw new Error('Invalid tools config: expected an object with "policy", "placement", and "providers".');
    }
    const policy = assertPolicyConfig(input?.policy);
    const placement = assertPlacementConfig(input?.placement);
    const providers = assertProvidersConfig(input?.providers);
    const pnpEnforcement = assertPnpEnforcement(input?.pnpEnforcement, "pnpEnforcement");
    const config = {
        policy: {
            allowed: normalizeToolList(assertStringArray(policy?.allowed, "policy.allowed")),
            blocked: normalizeToolList(assertStringArray(policy?.blocked, "policy.blocked")),
        },
        placement: {
            section: normalizeToolList(assertStringArray(placement?.section, "placement.section")).length
                ? normalizeToolList(assertStringArray(placement?.section, "placement.section"))
                : [...DEFAULT_PLACEMENT.section],
            item: normalizeToolList(assertStringArray(placement?.item, "placement.item")).length
                ? normalizeToolList(assertStringArray(placement?.item, "placement.item"))
                : [...DEFAULT_PLACEMENT.item],
            passage: normalizeToolList(assertStringArray(placement?.passage, "placement.passage")).length
                ? normalizeToolList(assertStringArray(placement?.passage, "placement.passage"))
                : [...DEFAULT_PLACEMENT.passage],
        },
        providers,
    };
    if (pnpEnforcement) {
        config.pnpEnforcement = pnpEnforcement;
    }
    return config;
}
//# sourceMappingURL=tools-config-normalizer.js.map