//! Parse `username@domain` federated addresses.
//!
//! A bare `username` (no `@`) is treated as local.

#![allow(dead_code)] // federation not yet wired up

/// A parsed federated address.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FederatedAddress {
    pub username: String,
    pub domain: Option<String>,
}

impl FederatedAddress {
    /// Parse a `user@domain` string. Bare `user` → domain is `None`.
    pub fn parse(input: &str) -> Self {
        // Split on the *last* '@' so usernames can contain '@' in theory.
        match input.rsplit_once('@') {
            Some((user, domain)) if !domain.is_empty() && !user.is_empty() => Self {
                username: user.to_string(),
                domain: Some(domain.to_string()),
            },
            _ => Self {
                username: input.to_string(),
                domain: None,
            },
        }
    }

    /// Returns true if this address refers to a local user (no domain or domain matches local).
    pub fn is_local(&self, local_domain: &str) -> bool {
        match &self.domain {
            None => true,
            Some(d) => d == local_domain,
        }
    }
}

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

    #[test]
    fn bare_username() {
        let addr = FederatedAddress::parse("alice");
        assert_eq!(addr.username, "alice");
        assert_eq!(addr.domain, None);
        assert!(addr.is_local("example.com"));
    }

    #[test]
    fn user_at_domain() {
        let addr = FederatedAddress::parse("alice@remote.example.com");
        assert_eq!(addr.username, "alice");
        assert_eq!(addr.domain, Some("remote.example.com".into()));
        assert!(!addr.is_local("local.example.com"));
        assert!(addr.is_local("remote.example.com"));
    }

    #[test]
    fn trailing_at_is_bare() {
        let addr = FederatedAddress::parse("alice@");
        assert_eq!(addr.username, "alice@");
        assert_eq!(addr.domain, None);
    }

    #[test]
    fn leading_at_is_bare() {
        let addr = FederatedAddress::parse("@domain.com");
        assert_eq!(addr.username, "@domain.com");
        assert_eq!(addr.domain, None);
    }

    #[test]
    fn multiple_at_uses_last() {
        let addr = FederatedAddress::parse("user@org@domain.com");
        assert_eq!(addr.username, "user@org");
        assert_eq!(addr.domain, Some("domain.com".into()));
    }
}
