//! User type definition
//! 
//! This module defines the User type and related structures.

use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};

/// User information
/// 
/// Represents a user in the Veza system.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct User {
    /// User ID (can be database ID or UUID depending on implementation)
    pub id: i64,
    /// Unique username
    pub username: String,
    /// User email address
    pub email: String,
    /// Optional display name
    #[serde(skip_serializing_if = "Option::is_none")]
    pub display_name: Option<String>,
    /// Optional avatar URL
    #[serde(skip_serializing_if = "Option::is_none")]
    pub avatar_url: Option<String>,
    /// User creation timestamp
    #[serde(skip_serializing_if = "Option::is_none")]
    pub created_at: Option<DateTime<Utc>>,
    /// User last update timestamp
    #[serde(skip_serializing_if = "Option::is_none")]
    pub updated_at: Option<DateTime<Utc>>,
}

impl User {
    /// Create a new User instance
    pub fn new(id: i64, username: String, email: String) -> Self {
        Self {
            id,
            username,
            email,
            display_name: None,
            avatar_url: None,
            created_at: None,
            updated_at: None,
        }
    }

    /// Validate user data
    pub fn validate(&self) -> Result<(), String> {
        if self.username.is_empty() {
            return Err("Username cannot be empty".to_string());
        }
        if self.email.is_empty() {
            return Err("Email cannot be empty".to_string());
        }
        if !self.email.contains('@') {
            return Err("Invalid email format".to_string());
        }
        Ok(())
    }
}

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

    #[test]
    fn test_user_new() {
        let user = User::new(1, "testuser".to_string(), "test@example.com".to_string());
        assert_eq!(user.id, 1);
        assert_eq!(user.username, "testuser");
        assert_eq!(user.email, "test@example.com");
        assert!(user.display_name.is_none());
        assert!(user.avatar_url.is_none());
    }

    #[test]
    fn test_user_serialize() {
        let user = User::new(1, "testuser".to_string(), "test@example.com".to_string());
        let json = serde_json::to_string(&user).unwrap();
        assert!(json.contains("\"id\":1"));
        assert!(json.contains("\"username\":\"testuser\""));
        assert!(json.contains("\"email\":\"test@example.com\""));
    }

    #[test]
    fn test_user_deserialize() {
        let json = r#"{"id":1,"username":"testuser","email":"test@example.com"}"#;
        let user: User = serde_json::from_str(json).unwrap();
        assert_eq!(user.id, 1);
        assert_eq!(user.username, "testuser");
        assert_eq!(user.email, "test@example.com");
    }

    #[test]
    fn test_user_validate_success() {
        let user = User::new(1, "testuser".to_string(), "test@example.com".to_string());
        assert!(user.validate().is_ok());
    }

    #[test]
    fn test_user_validate_empty_username() {
        let user = User::new(1, "".to_string(), "test@example.com".to_string());
        assert!(user.validate().is_err());
    }

    #[test]
    fn test_user_validate_empty_email() {
        let user = User::new(1, "testuser".to_string(), "".to_string());
        assert!(user.validate().is_err());
    }

    #[test]
    fn test_user_validate_invalid_email() {
        let user = User::new(1, "testuser".to_string(), "invalid-email".to_string());
        assert!(user.validate().is_err());
    }
}

