pub mod config;
pub mod migrate;
pub mod pool;

pub use config::DbConfig;
pub use pool::SurrealPool;

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("SurrealDB connect failed: {0}")]
    Connect(String),

    #[error("SurrealDB migration failed: {0}")]
    Migration(String),

    #[error("SurrealDB query failed: {0}")]
    Query(String),

    #[error("SurrealDB health check failed: {0}")]
    Health(String),

    #[error("Serialization error: {0}")]
    Serialization(String),
}

pub type Result<T> = std::result::Result<T, Error>;

#[cfg(test)]
mod tests {
    use super::*;
    use surrealdb::types::{RecordId, SurrealValue};

    #[derive(Debug, SurrealValue)]
    #[surreal(crate = "surrealdb::types")]
    struct Task {
        id: Option<RecordId>,
        name: String,
    }

    #[tokio::test]
    async fn connect_memory_and_migrate() {
        let pool = SurrealPool::connect(&DbConfig::Memory)
            .await
            .expect("in-memory connect should succeed");
        pool.health().await.expect("health check should pass");
    }

    #[tokio::test]
    async fn roundtrip_insert_select() {
        let pool = SurrealPool::connect(&DbConfig::Memory)
            .await
            .expect("connect");

        let db = pool.db();
        db.query("USE NS orchestrator DB provisioning")
            .await
            .expect("use ns");

        let _: Vec<Task> = db
            .create("tasks")
            .content(Task { id: None, name: "test-task".into() })
            .await
            .expect("insert");

        let results: Vec<Task> = db.select("tasks").await.expect("select");
        assert!(results.iter().any(|t| t.name == "test-task"));
    }
}
