//! Database helpers shared across the workspace.
//!
//! `tenant_filter` returns the BSON filter that every query and update
//! against a tenant-scoped collection MUST include. Centralising it here
//! makes the rule grep-able and keeps query call-sites from accidentally
//! omitting it.
//!
//! Future work (M7.2+): each collection model grows a `tenant_id` field
//! and every `find` / `update_*` / `delete_*` call gets this filter
//! merged in. The migration to per-collection scoping is tracked
//! separately — this helper is the building block.

use bson::{doc, Document};

use crate::TenantContext;

/// Returns `{ "tenant_id": <ctx.tenant_id> }`. Merge this into every
/// query filter against a tenant-scoped collection.
///
/// Use [`tenant_filter_merge`] when you need to combine it with other
/// query conditions — it preserves both halves without overwriting.
pub fn tenant_filter(ctx: &TenantContext) -> Document {
    doc! { "tenant_id": &ctx.tenant_id }
}

/// Returns the tenant filter merged with caller-supplied conditions.
/// The tenant_id always wins on key conflict — callers cannot
/// accidentally override the scoping.
pub fn tenant_filter_merge(ctx: &TenantContext, mut extra: Document) -> Document {
    extra.insert("tenant_id", &ctx.tenant_id);
    extra
}

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

    fn ctx() -> TenantContext {
        TenantContext {
            tenant_id: "t-abc".to_string(),
            tenant_slug: "acme".to_string(),
            org_roles: vec![],
            products: vec![],
            plan: "starter".to_string(),
            status: TenantStatus::Active,
            user_id: "u-1".to_string(),
            user_name: None,
        }
    }

    #[test]
    fn produces_tenant_id_filter() {
        let f = tenant_filter(&ctx());
        assert_eq!(f.get_str("tenant_id"), Ok("t-abc"));
        assert_eq!(f.len(), 1);
    }

    #[test]
    fn merge_preserves_extra_conditions() {
        let extra = doc! { "status": "open", "severity": "high" };
        let f = tenant_filter_merge(&ctx(), extra);
        assert_eq!(f.get_str("tenant_id"), Ok("t-abc"));
        assert_eq!(f.get_str("status"), Ok("open"));
        assert_eq!(f.get_str("severity"), Ok("high"));
    }

    #[test]
    fn merge_overrides_caller_tenant_id() {
        let extra = doc! { "tenant_id": "evil-other", "status": "open" };
        let f = tenant_filter_merge(&ctx(), extra);
        assert_eq!(f.get_str("tenant_id"), Ok("t-abc"));
        assert_eq!(f.get_str("status"), Ok("open"));
    }
}
