/** Caller defines the trigger thresholds; reasonix's defaults are 10/2. */
const DEFAULT_LEAF_LIMIT = 10;
const DEFAULT_DEPTH_LIMIT = 2;
export function analyzeSchema(schema, opts = {}) {
    if (!schema)
        return { shouldFlatten: false, leafCount: 0, maxDepth: 0 };
    const leafLimit = opts.leafLimit ?? DEFAULT_LEAF_LIMIT;
    const depthLimit = opts.depthLimit ?? DEFAULT_DEPTH_LIMIT;
    let leafCount = 0;
    let maxDepth = 0;
    walk(schema, 0, (depth, isLeaf) => {
        if (isLeaf)
            leafCount++;
        if (depth > maxDepth)
            maxDepth = depth;
    });
    return {
        shouldFlatten: leafCount > leafLimit || maxDepth > depthLimit,
        leafCount,
        maxDepth,
    };
}
export function flattenSchema(schema) {
    const flatProps = {};
    const required = [];
    collect('', schema, flatProps, required, true);
    return {
        type: 'object',
        properties: flatProps,
        required,
    };
}
export function nestArguments(flatArgs) {
    const out = {};
    for (const [key, value] of Object.entries(flatArgs)) {
        setByPath(out, key.split('.'), value);
    }
    return out;
}
function walk(schema, depth, visit) {
    if (schema.type === 'object' && schema.properties) {
        for (const child of Object.values(schema.properties)) {
            walk(child, depth + 1, visit);
        }
        return;
    }
    if (schema.type === 'array' && schema.items) {
        walk(schema.items, depth + 1, visit);
        return;
    }
    visit(depth, true);
}
function collect(prefix, schema, out, required, isRootRequired) {
    if (schema.type === 'object' && schema.properties) {
        const requiredSet = new Set(schema.required ?? []);
        for (const [key, child] of Object.entries(schema.properties)) {
            const nextPrefix = prefix ? `${prefix}.${key}` : key;
            const childRequired = isRootRequired && requiredSet.has(key);
            collect(nextPrefix, child, out, required, childRequired);
        }
        return;
    }
    out[prefix] = schema;
    if (isRootRequired)
        required.push(prefix);
}
function setByPath(target, path, value) {
    let cur = target;
    for (let i = 0; i < path.length - 1; i++) {
        const key = path[i];
        const next = cur[key];
        if (typeof next !== 'object' || next === null)
            cur[key] = {};
        cur = cur[key];
    }
    cur[path[path.length - 1]] = value;
}
