// ── store_memory.go ─────────────────────────
// MemoryStore interface for v0.18.0.
// Add this interface to store/interfaces.go and add
//   Memories  MemoryStore
// to the Stores struct.

package store

import (
	"context"

	"chat-switchboard/models"
)

// =========================================
// MEMORY STORE (v0.18.0)
// =========================================

type MemoryStore interface {
	// Upsert creates or updates a memory (matched on scope+owner+user+key).
	// If a memory with the same key exists, value/confidence/status are updated.
	Upsert(ctx context.Context, m *models.Memory) error

	// Update modifies an existing memory by ID. Use for handler edits where
	// the key may change (Upsert conflicts on composite key, not on ID).
	Update(ctx context.Context, m *models.Memory) error

	// GetByID returns a single memory by ID.
	GetByID(ctx context.Context, id string) (*models.Memory, error)

	// List returns memories matching the filter criteria.
	List(ctx context.Context, f models.MemoryFilter) ([]models.Memory, error)

	// Delete hard-deletes a memory by ID.
	Delete(ctx context.Context, id string) error

	// Archive sets status to 'archived' (soft delete).
	Archive(ctx context.Context, id string) error

	// Recall returns active memories relevant to a query, merging scopes.
	// Combines user + persona + persona_user memories for the given context.
	// Results are ordered by confidence DESC, updated_at DESC.
	Recall(ctx context.Context, userID string, personaID *string, query string, limit int) ([]models.Memory, error)

	// CountByOwner returns the number of active memories for a scope+owner.
	CountByOwner(ctx context.Context, scope, ownerID string) (int, error)

	// ListByStatus returns all memories with the given status across all owners.
	// Used by admin review endpoints. Results ordered by created_at DESC.
	ListByStatus(ctx context.Context, status string, limit int) ([]models.Memory, error)

	// RecallHybrid returns active memories using vector similarity + keyword search.
	// If queryVec is nil/empty, falls back to keyword-only (same as Recall).
	RecallHybrid(ctx context.Context, userID string, personaID *string, query string, queryVec []float64, limit int) ([]models.Memory, error)

	// ── CS5b additions (v0.29.0) ──

	// SetEmbedding updates the embedding vector for a memory. Handles dialect differences.
	SetEmbedding(ctx context.Context, id, embedding string) error

	// GetLastExtractionMessageID returns the last processed message ID from the extraction log.
	// Returns "" if no log entry exists.
	GetLastExtractionMessageID(ctx context.Context, channelID, userID string) (string, error)

	// UpsertExtractionLog creates or updates the memory extraction log entry.
	UpsertExtractionLog(ctx context.Context, channelID, userID, lastMessageID string, count int) error

	// ── v0.30.1 — Memory Compaction ──

	// DecayConfidence reduces confidence for active memories not updated since olderThan.
	// Formula: new_confidence = confidence * decayFactor. Skips memories with confidence <= 0.1.
	// Returns the number of affected rows.
	DecayConfidence(ctx context.Context, olderThan string, decayFactor float64) (int, error)

	// Prune archives active memories whose confidence has dropped below the threshold.
	// Returns the number of archived rows.
	Prune(ctx context.Context, belowConfidence float64) (int, error)
}
