//! LoadBalancer types

use serde::{Deserialize, Serialize};
use uuid::Uuid;

/// Unique identifier for a load balancer
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct LoadBalancerId(Uuid);

impl LoadBalancerId {
    /// Create a new random LoadBalancerId
    pub fn new() -> Self {
        Self(Uuid::new_v4())
    }

    /// Create from existing UUID
    pub fn from_uuid(uuid: Uuid) -> Self {
        Self(uuid)
    }

    /// Get the inner UUID
    pub fn as_uuid(&self) -> &Uuid {
        &self.0
    }
}

impl Default for LoadBalancerId {
    fn default() -> Self {
        Self::new()
    }
}

impl std::fmt::Display for LoadBalancerId {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

/// Load balancer status
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[derive(Default)]
pub enum LoadBalancerStatus {
    /// Load balancer is being provisioned
    #[default]
    Provisioning,
    /// Load balancer is active and handling traffic
    Active,
    /// Load balancer is updating configuration
    Updating,
    /// Load balancer has an error
    Error,
    /// Load balancer is being deleted
    Deleting,
}


/// Load balancer resource
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoadBalancer {
    /// Unique identifier
    pub id: LoadBalancerId,
    /// Human-readable name
    pub name: String,
    /// Organization ID (multi-tenant)
    pub org_id: String,
    /// Project ID (multi-tenant)
    pub project_id: String,
    /// Description
    pub description: Option<String>,
    /// Current status
    pub status: LoadBalancerStatus,
    /// VIP address (virtual IP)
    pub vip_address: Option<String>,
    /// Creation timestamp (Unix epoch seconds)
    pub created_at: u64,
    /// Last update timestamp
    pub updated_at: u64,
}

impl LoadBalancer {
    /// Create a new load balancer
    pub fn new(name: impl Into<String>, org_id: impl Into<String>, project_id: impl Into<String>) -> Self {
        let now = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap_or_default()
            .as_secs();
        
        Self {
            id: LoadBalancerId::new(),
            name: name.into(),
            org_id: org_id.into(),
            project_id: project_id.into(),
            description: None,
            status: LoadBalancerStatus::Provisioning,
            vip_address: None,
            created_at: now,
            updated_at: now,
        }
    }
}

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

    #[test]
    fn test_loadbalancer_creation() {
        let lb = LoadBalancer::new("test-lb", "org-1", "proj-1");
        assert_eq!(lb.name, "test-lb");
        assert_eq!(lb.org_id, "org-1");
        assert_eq!(lb.project_id, "proj-1");
        assert_eq!(lb.status, LoadBalancerStatus::Provisioning);
    }
}
