import { z } from 'zod';
import { buildBackendTargetKey, isBuiltInAgentTarget } from '../backendTargets/backendTargetRef.js';
function setByPath(obj, path, value) {
    const parts = String(path ?? '')
        .split('.')
        .map((p) => p.trim())
        .filter(Boolean);
    if (parts.length === 0)
        return;
    let cur = obj;
    for (let i = 0; i < parts.length - 1; i += 1) {
        const key = parts[i];
        const next = cur[key];
        if (!next || typeof next !== 'object' || Array.isArray(next)) {
            cur[key] = {};
        }
        cur = cur[key];
    }
    cur[parts[parts.length - 1]] = value;
}
function getByPath(obj, path) {
    const parts = String(path ?? '')
        .split('.')
        .map((p) => p.trim())
        .filter(Boolean);
    if (parts.length === 0)
        return undefined;
    let cur = obj;
    for (const part of parts) {
        if (!cur || typeof cur !== 'object' || Array.isArray(cur) || !(part in cur)) {
            return undefined;
        }
        cur = cur[part];
    }
    return cur;
}
function splitPath(path) {
    return String(path ?? '')
        .split('.')
        .map((part) => part.trim())
        .filter(Boolean);
}
function cloneSeedValue(value) {
    if (Array.isArray(value))
        return value.map((entry) => cloneSeedValue(entry));
    if (!value || typeof value !== 'object')
        return value;
    return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, cloneSeedValue(entry)]));
}
function unwrapSeedSchema(schema) {
    let current = schema;
    let optional = false;
    let nullable = false;
    for (;;) {
        if (current instanceof z.ZodOptional) {
            optional = true;
            current = current._def.innerType;
            continue;
        }
        if (current instanceof z.ZodDefault) {
            optional = true;
            current = current._def.innerType;
            continue;
        }
        if (current instanceof z.ZodNullable) {
            nullable = true;
            current = current._def.innerType;
            continue;
        }
        if (current instanceof z.ZodPipe) {
            current = current._def.in;
            continue;
        }
        break;
    }
    return { schema: current, optional, nullable };
}
function readDefaultValueAtPath(value, pathParts) {
    if (pathParts.length === 0)
        return value;
    let current = value;
    for (const part of pathParts) {
        if (!current || typeof current !== 'object' || Array.isArray(current) || !(part in current)) {
            return undefined;
        }
        current = current[part];
    }
    return current;
}
function readSchemaSeedDefaultAtPath(schema, path) {
    const pathParts = splitPath(path);
    const parsed = schema.safeParse(undefined);
    if (parsed.success && parsed.data !== undefined) {
        const value = readDefaultValueAtPath(parsed.data, pathParts);
        if (value !== undefined || pathParts.length === 0) {
            return { hasDefault: true, value };
        }
    }
    if (pathParts.length === 0) {
        return { hasDefault: false, value: undefined };
    }
    const unwrapped = unwrapSeedSchema(schema);
    if (unwrapped.optional || unwrapped.nullable) {
        return { hasDefault: false, value: undefined };
    }
    if (unwrapped.schema instanceof z.ZodObject) {
        const shape = unwrapped.schema.shape ?? unwrapped.schema._def?.shape ?? {};
        const [head, ...rest] = pathParts;
        const childSchema = shape[head];
        if (childSchema) {
            return readSchemaSeedDefaultAtPath(childSchema, rest.join('.'));
        }
    }
    return { hasDefault: false, value: undefined };
}
function getFieldHints(spec) {
    return Array.isArray(spec.inputHints?.fields) ? spec.inputHints.fields : [];
}
function findPrimaryBackendSelectionField(hints) {
    // Convention: first multiselect field with an options source represents backend/engine selection.
    for (const hint of hints) {
        if (hint.widget !== 'multiselect')
            continue;
        if (typeof hint.optionsSourceId === 'string' && String(hint.optionsSourceId).trim().length > 0) {
            return hint;
        }
    }
    return null;
}
function findInstructionsField(hints) {
    for (const hint of hints) {
        if (hint.path === 'instructions')
            return hint;
    }
    for (const hint of hints) {
        if (hint.widget === 'textarea')
            return hint;
    }
    return null;
}
function buildPrimarySelectionSeedValue(fieldPath, params) {
    const path = String(fieldPath ?? '').trim();
    if (path === 'backendTargetKeys' || path.endsWith('.backendTargetKeys')) {
        if (params.defaultBackendTarget) {
            return [buildBackendTargetKey(params.defaultBackendTarget)];
        }
        const backendId = String(params.defaultBackendId ?? '').trim();
        return backendId ? [`agent:${backendId}`] : [];
    }
    const backendId = String(params.defaultBackendId ?? '').trim();
    if (backendId)
        return [backendId];
    if (params.defaultBackendTarget && isBuiltInAgentTarget(params.defaultBackendTarget)) {
        return [params.defaultBackendTarget.agentId];
    }
    return [];
}
export function buildActionDraftSeedInput(spec, ctx) {
    const hints = getFieldHints(spec);
    const seed = {};
    const backendField = findPrimaryBackendSelectionField(hints);
    if (backendField?.path && backendField.requireExplicitSelection !== true) {
        const selectionSeed = buildPrimarySelectionSeedValue(backendField.path, ctx);
        if (selectionSeed.length > 0) {
            setByPath(seed, backendField.path, selectionSeed);
        }
    }
    const instructions = ctx.instructions === null || ctx.instructions === undefined ? null : String(ctx.instructions);
    if (instructions !== null) {
        const instructionsField = findInstructionsField(hints);
        if (instructionsField?.path) {
            setByPath(seed, instructionsField.path, instructions);
        }
    }
    for (const hint of hints) {
        if (getByPath(seed, hint.path) !== undefined)
            continue;
        const fieldDefault = readSchemaSeedDefaultAtPath(spec.inputSchema, hint.path);
        if (!fieldDefault.hasDefault)
            continue;
        setByPath(seed, hint.path, cloneSeedValue(fieldDefault.value));
    }
    // Seed required selects with their first option. This keeps draft UIs usable even when the user
    // starts via a chip and the underlying input schema requires a value.
    for (const hint of hints) {
        if (hint.widget !== 'select')
            continue;
        if (hint.required !== true)
            continue;
        if (getByPath(seed, hint.path) !== undefined)
            continue;
        const options = Array.isArray(hint.options) ? hint.options : [];
        if (options.length === 0)
            continue;
        setByPath(seed, hint.path, options[0].value);
    }
    return seed;
}
//# sourceMappingURL=actionDraftSeed.js.map