//! TLS Certificate types

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

use crate::LoadBalancerId;

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

impl CertificateId {
    /// Create a new random CertificateId
    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 CertificateId {
    fn default() -> Self {
        Self::new()
    }
}

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

/// TLS Certificate
///
/// Stores X.509 certificates and private keys for TLS termination.
/// Certificates are stored in PEM format and should be encrypted at rest
/// in production deployments.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Certificate {
    /// Unique identifier
    pub id: CertificateId,
    /// Parent load balancer
    pub loadbalancer_id: LoadBalancerId,
    /// Human-readable name
    pub name: String,

    /// PEM-encoded certificate chain
    /// Should include the server certificate and any intermediate CA certificates
    pub certificate: String,

    /// PEM-encoded private key
    /// WARNING: Should be encrypted at rest in production
    pub private_key: String,

    /// Certificate type
    pub cert_type: CertificateType,

    /// Expiration timestamp (Unix epoch)
    pub expires_at: u64,

    /// Creation timestamp (Unix epoch)
    pub created_at: u64,
    /// Last update timestamp (Unix epoch)
    pub updated_at: u64,
}

/// Certificate type
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CertificateType {
    /// Standard server certificate for TLS termination
    Server,
    /// CA certificate for client authentication
    ClientCa,
    /// SNI certificate for virtual hosting
    Sni,
}

impl Default for CertificateType {
    fn default() -> Self {
        Self::Server
    }
}

impl Certificate {
    /// Create a new certificate
    pub fn new(
        name: impl Into<String>,
        loadbalancer_id: LoadBalancerId,
        certificate: impl Into<String>,
        private_key: impl Into<String>,
        cert_type: CertificateType,
        expires_at: u64,
    ) -> Self {
        let now = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap_or_default()
            .as_secs();

        Self {
            id: CertificateId::new(),
            loadbalancer_id,
            name: name.into(),
            certificate: certificate.into(),
            private_key: private_key.into(),
            cert_type,
            expires_at,
            created_at: now,
            updated_at: now,
        }
    }
}
