/**
 * Extract merged `args` JSON Schema from `task-engine-run-contracts.schema.json`.
 * Keep behavior aligned with `scripts/lib/extract-contract-args.mjs` (refresh + check scripts).
 */
export function resolveJsonPointer(root, ref) {
    if (!ref.startsWith("#/")) {
        throw new Error(`Unsupported ref (expected #/…): ${ref}`);
    }
    const parts = ref.slice(2).split("/").map((p) => p.replace(/~1/g, "/").replace(/~0/g, "~"));
    let cur = root;
    for (const p of parts) {
        if (cur == null || typeof cur !== "object") {
            throw new Error(`Broken ref path ${ref} at ${p}`);
        }
        cur = cur[p];
    }
    return cur;
}
function resolveNode(root, node) {
    if (typeof node.$ref === "string") {
        return resolveNode(root, resolveJsonPointer(root, node.$ref));
    }
    return node;
}
function mergeArgFragments(base, next) {
    const out = { ...base };
    if (next.type !== undefined) {
        out.type = next.type;
    }
    if (Array.isArray(next.required)) {
        const prev = Array.isArray(out.required) ? out.required : [];
        out.required = [...new Set([...prev, ...next.required])];
    }
    if (next.properties && typeof next.properties === "object" && !Array.isArray(next.properties)) {
        out.properties = {
            ...(typeof out.properties === "object" && out.properties !== null && !Array.isArray(out.properties)
                ? out.properties
                : {}),
            ...next.properties
        };
    }
    if (next.additionalProperties === false) {
        out.additionalProperties = false;
    }
    else if (next.additionalProperties === true && out.additionalProperties !== false) {
        out.additionalProperties = true;
    }
    if (next.oneOf !== undefined) {
        out.oneOf = next.oneOf;
    }
    if (next.anyOf !== undefined) {
        out.anyOf = next.anyOf;
    }
    if (next.allOf !== undefined) {
        out.allOf = next.allOf;
    }
    return out;
}
export function mergeArgsSchemaFromContract(root, contract) {
    const resolved = resolveNode(root, contract);
    const allOf = resolved.allOf;
    if (!Array.isArray(allOf)) {
        const props = resolved.properties;
        const args = props?.args;
        return args && typeof args === "object" ? structuredClone(args) : { type: "object" };
    }
    let merged = { type: "object" };
    for (const frag of allOf) {
        if (!frag || typeof frag !== "object") {
            continue;
        }
        const r = resolveNode(root, frag);
        const rProps = r.properties;
        const args = rProps?.args;
        if (!args || typeof args !== "object" || Array.isArray(args)) {
            continue;
        }
        merged = mergeArgFragments(merged, args);
    }
    return merged;
}
export function extractCommandArgsSchema(root, commandName) {
    const commands = root.properties
        ?.commands?.properties;
    if (!commands || typeof commands !== "object") {
        throw new Error("Invalid schema: missing properties.commands.properties");
    }
    const entry = commands[commandName];
    if (!entry) {
        throw new Error(`Unknown command '${commandName}' in schema`);
    }
    const contract = resolveNode(root, entry);
    return mergeArgsSchemaFromContract(root, contract);
}
