-- ==========================================
-- Chat Switchboard — 008 Memory
-- ==========================================
-- Long-term memory across conversations, extraction tracking.
-- Consolidated v0.28.0: adds last_compacted_at + decay_rate.
-- ==========================================

-- =========================================
-- MEMORIES
-- =========================================

CREATE TABLE IF NOT EXISTS memories (
    id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    scope             TEXT NOT NULL CHECK (scope IN ('user', 'persona', 'persona_user')),
    owner_id          UUID NOT NULL,
    user_id           UUID,
    key               TEXT NOT NULL,
    value             TEXT NOT NULL,
    source_channel_id UUID,
    confidence        REAL NOT NULL DEFAULT 1.0,
    status            TEXT NOT NULL DEFAULT 'active'
                      CHECK (status IN ('active', 'pending_review', 'archived')),
    embedding         vector(3072),

    -- Compaction support (v0.28.0)
    last_compacted_at TIMESTAMPTZ,
    decay_rate        REAL NOT NULL DEFAULT 0.0,

    created_at        TIMESTAMPTZ DEFAULT now(),
    updated_at        TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_memories_scope_owner
    ON memories(scope, owner_id, status)
    WHERE status = 'active';

CREATE INDEX IF NOT EXISTS idx_memories_persona_user
    ON memories(owner_id, user_id)
    WHERE scope = 'persona_user' AND status = 'active';

CREATE UNIQUE INDEX IF NOT EXISTS idx_memories_unique_key
    ON memories(scope, owner_id, COALESCE(user_id, '00000000-0000-0000-0000-000000000000'), key);

CREATE INDEX IF NOT EXISTS idx_memories_fts
    ON memories USING gin(to_tsvector('english', key || ' ' || value));

CREATE INDEX IF NOT EXISTS idx_memories_source_channel
    ON memories(source_channel_id)
    WHERE source_channel_id IS NOT NULL;

COMMENT ON TABLE memories IS 'Long-term memory facts persisted across conversations';
COMMENT ON COLUMN memories.scope IS 'user = personal facts; persona = shared; persona_user = per-user within a persona';
COMMENT ON COLUMN memories.owner_id IS 'user_id for user scope, persona_id for persona/persona_user scopes';
COMMENT ON COLUMN memories.confidence IS '0.0-1.0 confidence score — higher = more certain';
COMMENT ON COLUMN memories.last_compacted_at IS 'Last time this memory was evaluated by the compaction process';
COMMENT ON COLUMN memories.decay_rate IS 'Rate at which confidence decreases over time (0.0 = no decay)';

CREATE OR REPLACE FUNCTION update_memories_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_memories_updated_at ON memories;
CREATE TRIGGER trg_memories_updated_at
    BEFORE UPDATE ON memories
    FOR EACH ROW EXECUTE FUNCTION update_memories_updated_at();


-- =========================================
-- MEMORY EXTRACTION LOG
-- =========================================

CREATE TABLE IF NOT EXISTS memory_extraction_log (
    id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    channel_id    UUID NOT NULL,
    user_id       UUID NOT NULL,
    last_message_id UUID NOT NULL,
    extracted_at  TIMESTAMPTZ DEFAULT now(),
    memory_count  INT NOT NULL DEFAULT 0,
    UNIQUE(channel_id, user_id)
);

CREATE INDEX IF NOT EXISTS idx_mem_extract_log_channel
    ON memory_extraction_log(channel_id);

COMMENT ON TABLE memory_extraction_log IS 'Tracks extraction progress per channel+user to prevent re-processing';
