import { isStructuredApplyPatchPayload } from '../structured.js';
import { tryParseJson } from '../json/parse-loose.js';
import { asString } from '../validation/shared.js';
const resolveTopLevelFile = (record) => {
    const direct = asString(record.file) ??
        asString(record.path) ??
        asString(record.filepath) ??
        asString(record.filename);
    if (direct)
        return direct;
    // Shape fix: treat top-level target as file path when changes exist.
    const target = asString(record.target);
    if (target && Array.isArray(record.changes) && record.changes.length > 0) {
        return target;
    }
    return undefined;
};
const buildSingleChangePayload = (record) => {
    const kindRaw = asString(record.kind);
    if (!kindRaw)
        return undefined;
    const change = {
        kind: kindRaw.toLowerCase(),
        lines: record.lines ?? record.text ?? record.body,
        target: asString(record.target) ?? undefined,
        anchor: asString(record.anchor) ?? undefined
    };
    if (typeof record.use_anchor_indent === 'boolean') {
        change.use_anchor_indent = record.use_anchor_indent;
    }
    const changeFile = asString(record.file) ??
        asString(record.path) ??
        asString(record.filepath) ??
        asString(record.filename);
    if (changeFile) {
        change.file = changeFile;
    }
    return { ...(changeFile ? { file: changeFile } : {}), changes: [change] };
};
const coerceChangesArray = (value) => {
    const parsed = tryParseJson(value);
    if (!parsed)
        return undefined;
    if (Array.isArray(parsed)) {
        const items = parsed.filter((entry) => entry && typeof entry === 'object');
        if (!items.length)
            return undefined;
        // Ensure at least one entry looks like a structured change.
        if (!items.some((c) => typeof c.kind === 'string' && String(c.kind).trim()))
            return undefined;
        return items;
    }
    if (parsed && typeof parsed === 'object' && Array.isArray(parsed.changes)) {
        const items = parsed.changes.filter((entry) => entry && typeof entry === 'object');
        if (!items.length)
            return undefined;
        if (!items.some((c) => typeof c.kind === 'string' && String(c.kind).trim()))
            return undefined;
        return items;
    }
    return undefined;
};
export const coerceStructuredPayload = (record) => {
    const topLevelFile = resolveTopLevelFile(record);
    if (isStructuredApplyPatchPayload(record)) {
        if (topLevelFile && !asString(record.file)) {
            return { ...record, file: topLevelFile };
        }
        return record;
    }
    if (Array.isArray(record.changes) && record.changes.length === 0) {
        return undefined;
    }
    // Common shape error: { file, instructions: "[{...},{...}]" } where instructions contains JSON changes.
    if (!Array.isArray(record.changes)) {
        const changesFromInstructions = coerceChangesArray(record.instructions);
        if (changesFromInstructions) {
            return {
                ...(topLevelFile ? { file: topLevelFile } : {}),
                changes: changesFromInstructions
            };
        }
        // Another common shape: changes is a JSON string.
        const changesFromString = coerceChangesArray(record.changes);
        if (changesFromString) {
            return {
                ...(topLevelFile ? { file: topLevelFile } : {}),
                changes: changesFromString
            };
        }
        const editsFromString = coerceChangesArray(record.edits ?? record.operations ?? record.ops);
        if (editsFromString) {
            return {
                ...(topLevelFile ? { file: topLevelFile } : {}),
                changes: editsFromString
            };
        }
    }
    const single = buildSingleChangePayload(record);
    if (single)
        return single;
    return undefined;
};
