//! User entity write/read operations on `TidalDb`.

use std::collections::HashMap;

use crate::schema::{EntityId, TidalError};
use crate::storage::{Tag, encode_key};

use super::TidalDb;

impl TidalDb {
    /// Write (or overwrite) a user entity.
    ///
    /// Stores metadata and optional embedding under the user's `Tag::Meta` key
    /// in the users storage backend.
    ///
    /// # Errors
    ///
    /// - `TidalError::Internal` if no storage backend is wired.
    /// - `TidalError::Storage` on storage engine failure.
    pub fn write_user(
        &self,
        id: EntityId,
        metadata: &HashMap<String, String>,
    ) -> crate::Result<()> {
        self.require_writeable("write_user")?;
        let storage = self.storage()?;
        let key = encode_key(id, Tag::Meta, b"");
        let value = crate::entities::serialize_entity(None, metadata);
        storage
            .users_engine()
            .put(&key, &value)
            .map_err(TidalError::from)?;
        self.cohort_resolver.invalidate(id.as_u64());
        Ok(())
    }

    /// Read user metadata for a given entity ID.
    ///
    /// Returns `None` if the user does not exist in storage.
    ///
    /// # Errors
    ///
    /// - `TidalError::Internal` if no storage backend is wired.
    /// - `TidalError::Storage` on storage engine failure.
    pub fn get_user_metadata(
        &self,
        id: EntityId,
    ) -> crate::Result<Option<HashMap<String, String>>> {
        let storage = self.storage()?;
        let key = encode_key(id, Tag::Meta, b"");
        match storage.users_engine().get(&key) {
            Ok(Some(bytes)) => {
                let (_emb, meta) = crate::entities::deserialize_entity(&bytes);
                Ok(Some(meta))
            }
            Ok(None) => Ok(None),
            Err(e) => Err(TidalError::from(e)),
        }
    }
}
