//! Constructor for creating new Domain instances

use crate::error::{LazyDomainError, Result};
use crate::types::domain::Domain;

impl Domain {
    /// Creates a new Domain instance
    ///
    /// # Arguments
    ///
    /// * `name` - The domain name without TLD (e.g., "example")
    /// * `tld` - The top-level domain (e.g., "com")
    ///
    /// # Returns
    ///
    /// Returns `Ok(Domain)` if both name and TLD are non-empty,
    /// otherwise returns an error.
    ///
    /// # Errors
    ///
    /// Returns `LazyDomainError::InvalidDomain` if either name or TLD is empty.
    ///
    /// # Examples
    ///
    /// ```
    /// use lazydomain::types::Domain;
    ///
    /// let domain = Domain::new("example", "com").unwrap();
    /// assert_eq!(domain.name, "example");
    /// assert_eq!(domain.tld, "com");
    /// ```
    pub fn new(name: impl Into<String>, tld: impl Into<String>) -> Result<Self> {
        let name = name.into();
        let tld = tld.into();

        if name.is_empty() || tld.is_empty() {
            return Err(LazyDomainError::InvalidDomain(
                "Name and TLD cannot be empty".to_string(),
            ));
        }

        Ok(Domain { name, tld })
    }
}

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

    #[test]
    fn test_creates_valid_domain() {
        let domain = Domain::new("example", "com").unwrap();
        assert_eq!(domain.name, "example");
        assert_eq!(domain.tld, "com");
    }

    #[test]
    fn test_rejects_empty_name() {
        let result = Domain::new("", "com");
        assert!(result.is_err());
    }

    #[test]
    fn test_rejects_empty_tld() {
        let result = Domain::new("example", "");
        assert!(result.is_err());
    }

    #[test]
    fn test_accepts_string_types() {
        let domain = Domain::new("example".to_string(), "com".to_string()).unwrap();
        assert_eq!(domain.name, "example");
    }
}
