//! Federation routing: determine whether a recipient is local or remote.

use std::sync::Arc;

use crate::storage::Store;

/// Where a message should be delivered.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Destination {
    /// Recipient is on this server.
    Local,
    /// Recipient's home server is the given domain.
    Remote(String),
}

/// Resolve a recipient identity key to a routing destination.
///
/// 1. Check the `identity_home_servers` table for an explicit mapping.
/// 2. If no mapping exists, assume local (backwards compatible with single-server deployments).
pub fn resolve_destination(
    store: &Arc<dyn Store>,
    recipient_key: &[u8],
    local_domain: &str,
) -> Destination {
    match store.get_identity_home_server(recipient_key) {
        Ok(Some(domain)) if domain != local_domain => Destination::Remote(domain),
        _ => Destination::Local,
    }
}

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

    #[test]
    fn unknown_identity_routes_local() {
        let store: Arc<dyn Store> =
            Arc::new(crate::storage::FileBackedStore::open(
                tempfile::tempdir().unwrap().path(),
            ).unwrap());
        let dest = resolve_destination(&store, &[1u8; 32], "local.example.com");
        assert_eq!(dest, Destination::Local);
    }
}
