-- Migration: 007_versioning_schema.sql
-- Phase 7.1: Entity & Edge Versioning
-- Tracks full snapshots on every mutation for rollback capability

BEGIN;

-- Entity version snapshots (immutable)
CREATE TABLE IF NOT EXISTS memory_entity_version (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id VARCHAR(255) NOT NULL,
    version_num INTEGER NOT NULL,
    operation VARCHAR(20) NOT NULL CHECK (operation IN ('create', 'update', 'delete')),
    
    -- Full snapshot JSONB
    snapshot JSONB NOT NULL,
    
    -- Audit metadata
    changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    changed_by VARCHAR(255) NOT NULL,  -- JWT sub claim
    fields_changed TEXT[] DEFAULT '{}',
    
    -- Temporal
    t_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    
    -- Constraints
    UNIQUE(entity_id, version_num),
    CONSTRAINT valid_version_num CHECK (version_num > 0)
);

-- Edge version snapshots
CREATE TABLE IF NOT EXISTS memory_edge_version (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    edge_id UUID NOT NULL,
    version_num INTEGER NOT NULL,
    operation VARCHAR(20) NOT NULL CHECK (operation IN ('create', 'update', 'delete')),
    
    -- Full snapshot JSONB
    snapshot JSONB NOT NULL,
    
    -- Audit metadata
    changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    changed_by VARCHAR(255) NOT NULL,
    fields_changed TEXT[] DEFAULT '{}',
    
    -- Temporal
    t_created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    
    -- Constraints
    UNIQUE(edge_id, version_num),
    CONSTRAINT valid_version_num CHECK (version_num > 0)
);

-- Indexes for efficient lookups
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_version_entity_id 
    ON memory_entity_version(entity_id, version_num DESC);

CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_version_changed_at 
    ON memory_entity_version(changed_at DESC);

CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_entity_version_changed_by 
    ON memory_entity_version(changed_by);

CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_version_edge_id 
    ON memory_edge_version(edge_id, version_num DESC);

CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_version_changed_at 
    ON memory_edge_version(changed_at DESC);

CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_edge_version_changed_by 
    ON memory_edge_version(changed_by);

-- Immutability enforcement: version tables are append-only
CREATE OR REPLACE FUNCTION prevent_version_table_modification()
RETURNS TRIGGER AS $$
BEGIN
    RAISE EXCEPTION 'Version tables are immutable';
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER memory_entity_version_immutable
    BEFORE UPDATE OR DELETE ON memory_entity_version
    FOR EACH ROW EXECUTE FUNCTION prevent_version_table_modification();

CREATE TRIGGER memory_edge_version_immutable
    BEFORE UPDATE OR DELETE ON memory_edge_version
    FOR EACH ROW EXECUTE FUNCTION prevent_version_table_modification();

COMMIT;

-- Rollback (for reference):
-- DROP TRIGGER memory_entity_version_immutable ON memory_entity_version;
-- DROP TRIGGER memory_edge_version_immutable ON memory_edge_version;
-- DROP FUNCTION prevent_version_table_modification();
-- DROP TABLE memory_entity_version;
-- DROP TABLE memory_edge_version;
