use super::{
    MongodbConfigStore,
    serde::{transform_from_mongo, try_to_object_id},
};
use crate::storage::Error;
use crate::storage::config_store::adapters::mongodb::serde::try_to_uuid;
use mongodb::{ClientSession, Collection, bson::Document};
use pbbson::Model;
use pbbson::bson::doc;

pub async fn find<B: Clone + Send + Sync + ToString>(
    this: &MongodbConfigStore<B>,
    mut session: Option<&mut ClientSession>,
    bucket: B,
    id: &str,
) -> Result<Model, Error> {
    let coll: Collection<Document> = this.db.collection(&bucket.to_string());
    let filter = match try_to_object_id(id) {
        Ok(object_id) => doc! {"_id": object_id},
        Err(_e) => {
            let uuid = try_to_uuid(id)?;
            doc! {"_id": uuid}
        }
    };

    let maybe_document = {
        let op = coll.find_one(filter);
        if let Some(ref mut session) = session {
            op.session(&mut **session).await?
        } else {
            op.await?
        }
    };
    match maybe_document {
        None => Err(Error::not_found("No such record")),
        Some(document) => Ok(transform_from_mongo(document.into())?),
    }
}
