// Exercises Migrations.applyWith against fixture steps and prints a verdict per
// case. Run by tests/quickshell/migrations-contract.sh.
//
// Fixture steps rather than the real list: the real one is empty until the
// first breaking schema change, and a mechanism that has never been run against
// a failing step is not one to discover the behaviour of during an upgrade.

import Quickshell
import QtQuick
import qs.config

ShellRoot {
    Component.onCompleted: {
        const steps = [
            { version: 2, describe: "add b", migrate: v => { v.b = (v.a ?? 0) + 1; return v; } },
            { version: 3, describe: "add c", migrate: v => { v.c = "three"; return v; } },
            { version: 4, describe: "explode", migrate: v => { throw new Error("boom"); } }
        ];
        const results = {};

        // No version at all: a file written before versioning. Stamped, never
        // migrated.
        let r = Migrations.applyWith({ a: 1 }, steps, 3, 1);
        results.unversioned = { v: r.values.schemaVersion, migrated: r.migrated,
                                changed: r.changed, untouched: r.values.b === undefined };

        // Older file: every step above its version runs, in order.
        r = Migrations.applyWith({ a: 1, schemaVersion: 1 }, steps, 3, 1);
        results.upgrade = { v: r.values.schemaVersion, b: r.values.b, c: r.values.c,
                            count: r.applied.length, migrated: r.migrated };

        // Already current: nothing runs.
        r = Migrations.applyWith({ schemaVersion: 3, keep: "me" }, steps, 3, 1);
        results.current = { v: r.values.schemaVersion, migrated: r.migrated,
                            kept: r.values.keep === "me", b: r.values.b === undefined };

        // From the future: left completely alone, including its unknown keys.
        r = Migrations.applyWith({ schemaVersion: 9, futureKey: "x" }, steps, 3, 1);
        results.future = { v: r.values.schemaVersion, migrated: r.migrated,
                           changed: r.changed, kept: r.values.futureKey === "x" };

        // A failing step stops at the last good version rather than losing the
        // file or skipping past the failure forever.
        r = Migrations.applyWith({ schemaVersion: 1, a: 5 }, steps, 4, 1);
        results.failure = { v: r.values.schemaVersion, b: r.values.b, c: r.values.c,
                            kept: r.values.a === 5, count: r.applied.length };

        // Unknown keys survive a migration: rolling back to an older Panama
        // must not discard a newer version's settings.
        r = Migrations.applyWith({ schemaVersion: 1, unknownFromFuture: true }, steps, 3, 1);
        results.preserved = { kept: r.values.unknownFromFuture === true };

        console.info("PANAMA-MIGRATIONS " + JSON.stringify(results));
        Qt.callLater(() => Qt.quit());
    }
}
