pub mod backend;
pub mod chunker;
pub mod embeddings;
pub mod markdown;
pub mod none;
pub mod sqlite;
pub mod traits;
pub mod vector;

pub use backend::{classify_memory_backend, default_memory_backend_key, MemoryBackendKind};
pub use chunker::{chunk_markdown, Chunk};
pub use embeddings::{
    create_embedding_provider, EmbeddingProvider, NoopEmbedding, OpenAiEmbedding,
};
pub use markdown::MarkdownMemory;
pub use none::NoneMemory;
pub use sqlite::SqliteMemory;
pub use traits::{Memory, MemoryCategory, MemoryEntry};
pub use vector::{bytes_to_vec, cosine_similarity, hybrid_merge, vec_to_bytes, ScoredResult};

use std::path::Path;

pub fn create_memory(backend: &str, workspace_dir: &Path) -> anyhow::Result<Box<dyn Memory>> {
    match classify_memory_backend(backend) {
        MemoryBackendKind::Sqlite => Ok(Box::new(SqliteMemory::new(workspace_dir)?)),
        MemoryBackendKind::Markdown => Ok(Box::new(MarkdownMemory::new(workspace_dir))),
        MemoryBackendKind::None => Ok(Box::new(NoneMemory::new())),
        MemoryBackendKind::Unknown => {
            tracing::warn!(
                "Unknown memory backend '{}', falling back to markdown",
                backend
            );
            Ok(Box::new(MarkdownMemory::new(workspace_dir)))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn factory_sqlite() {
        let tmp = tempfile::TempDir::new().unwrap();
        let mem = create_memory("sqlite", tmp.path()).unwrap();
        assert_eq!(mem.name(), "sqlite");
    }

    #[test]
    fn factory_markdown() {
        let tmp = tempfile::TempDir::new().unwrap();
        let mem = create_memory("markdown", tmp.path()).unwrap();
        assert_eq!(mem.name(), "markdown");
    }

    #[test]
    fn factory_none() {
        let tmp = tempfile::TempDir::new().unwrap();
        let mem = create_memory("none", tmp.path()).unwrap();
        assert_eq!(mem.name(), "none");
    }

    #[test]
    fn factory_unknown_falls_back_to_markdown() {
        let tmp = tempfile::TempDir::new().unwrap();
        let mem = create_memory("redis", tmp.path()).unwrap();
        assert_eq!(mem.name(), "markdown");
    }
}
