-- Revision history: the undo substrate (#48).
--
-- The unit of undo is the OPERATION, not the row. "Empty the garlic bed and
-- plant cucumbers" touches one object and many plantings; undoing half of that
-- is worse than useless. So a change_set groups the row-level revisions it
-- produced, and revert replays their inverses.
--
-- Two properties this schema is built around:
--   * Revert is itself a change set (reverts_id points at its target). History is
--     append-only and never rewritten, so an undo can be undone. git revert, not
--     git reset.
--   * Every revision carries full JSON row snapshots INCLUDING version, which is
--     what the revert guard compares against so a later edit is reported as a
--     conflict rather than silently clobbered.
--
-- JSON snapshots rather than a shadow table per entity: the rows are small,
-- household scale makes storage a non-issue, and one code path covers all three
-- entity types.
--
-- Deliberate gap: garden DELETION is not revertible. Dropping a garden cascades
-- its objects and plantings without the service ever seeing them, and the
-- ON DELETE CASCADE below would take the history with it. The history UI says so
-- rather than pretending otherwise.
CREATE TABLE change_sets (
    id           INTEGER PRIMARY KEY,
    garden_id    INTEGER NOT NULL REFERENCES gardens (id) ON DELETE CASCADE,
    actor_id     INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
    source       TEXT    NOT NULL CHECK (source IN ('ui', 'agent', 'api')),
    summary      TEXT    NOT NULL DEFAULT '',
    agent_run_id TEXT,                                   -- executus run id when source='agent'
    reverts_id   INTEGER REFERENCES change_sets (id),    -- set when this change set reverts another
    created_at   TEXT    NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

-- The history panel's only query: one garden, newest first.
CREATE INDEX idx_change_sets_garden ON change_sets (garden_id, created_at DESC);

-- "Has this change set been reverted?" — the list marks reverted entries, so the
-- lookup by target must not be a scan.
CREATE INDEX idx_change_sets_reverts ON change_sets (reverts_id) WHERE reverts_id IS NOT NULL;

CREATE TABLE revisions (
    id            INTEGER PRIMARY KEY,
    change_set_id INTEGER NOT NULL REFERENCES change_sets (id) ON DELETE CASCADE,
    seq           INTEGER NOT NULL,                      -- order within the change set
    entity_type   TEXT    NOT NULL CHECK (entity_type IN ('garden', 'object', 'planting')),
    entity_id     INTEGER NOT NULL,
    op            TEXT    NOT NULL CHECK (op IN ('create', 'update', 'delete')),
    before        TEXT,                                  -- JSON row snapshot; NULL for create
    after         TEXT                                   -- JSON row snapshot; NULL for delete
);

CREATE INDEX idx_revisions_change_set ON revisions (change_set_id, seq);
