/**
 * Rule: crud-roundtrip
 *
 * The core CURVED lifecycle for every top-level entity, end to end:
 *
 *   create → retrieve (the created value round-trips)
 *          → update  → retrieve (the new value round-trips)
 *          → delete  → retrieve (now rejected — it's gone)
 *
 * Derived purely from attributes + the controller's available ops. No new
 * spec data needed. Top-level models only (no required belongsTo — parent
 * seeding is out of v1 scope). The update arm is included only when the
 * controller supports `update` AND the model has a mutable business string
 * field to change.
 */
import { buildTopLevelPayload, opAvailable, parseLifecyclePaths } from '../_shared.js';
export const RULE_ID = 'crud-roundtrip';
export const crudRoundtrip = (spec) => {
    const cases = [];
    for (const model of spec.models) {
        // Needs the full create/retrieve/delete surface to round-trip.
        if (!opAvailable(spec, model.name, 'create'))
            continue;
        if (!opAvailable(spec, model.name, 'retrieve'))
            continue;
        if (!opAvailable(spec, model.name, 'delete'))
            continue;
        const marker = `sc-crud-${model.name}`;
        const payload = buildTopLevelPayload(model, marker);
        if (!payload)
            continue; // needs parent seeding — out of v1 scope
        // Find a business string field we filled, to assert round-trip + mutate.
        const lifecycleFields = new Set(parseLifecyclePaths(model).map(p => p.field));
        const stringField = Object.entries(payload).find(([k, v]) => typeof v === 'string' && !lifecycleFields.has(k) && v.startsWith(marker));
        const steps = [
            { op: 'create', model: model.name, payload, bindAs: 'e', expect: { kind: 'ok' } },
        ];
        if (stringField) {
            const [field, created] = stringField;
            // created value round-trips on retrieve
            steps.push({ op: 'retrieve', model: model.name, idExpr: 'e.id', expect: { kind: 'state', field, value: created } });
            if (opAvailable(spec, model.name, 'update')) {
                const updated = `${created}-updated`;
                steps.push({ op: 'update', model: model.name, idExpr: 'e.id', payload: { [field]: updated }, expect: { kind: 'ok' } });
                steps.push({ op: 'retrieve', model: model.name, idExpr: 'e.id', expect: { kind: 'state', field, value: updated } });
            }
        }
        else {
            // No mutable string field — at least confirm the entity is retrievable.
            steps.push({ op: 'retrieve', model: model.name, idExpr: 'e.id', expect: { kind: 'ok' } });
        }
        steps.push({ op: 'delete', model: model.name, idExpr: 'e.id', expect: { kind: 'ok' } });
        steps.push({ op: 'retrieve', model: model.name, idExpr: 'e.id', expect: { kind: 'rejected' } });
        cases.push({
            ruleId: RULE_ID,
            specElement: model.name,
            name: `[${RULE_ID}] ${model.name} create -> retrieve -> update -> delete round-trips`,
            steps,
        });
    }
    return cases;
};
//# sourceMappingURL=crud-roundtrip.js.map