//! Shared TLS types for Foxhunt services.
//!
//! This module contains type definitions shared across all service TLS configurations:
//! - [`TlsProtocolVersion`] - TLS 1.2 / 1.3 selection
//! - [`UserRole`] - RBAC roles extracted from client certificates
//! - [`ClientIdentity`] - Client identity extracted from mTLS certificates
//!
//! Each service retains its own `TlsConfig` struct and validation logic because
//! the validation approaches differ (async vs sync, delegated vs monolithic).

/// TLS protocol version options.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TlsProtocolVersion {
    /// TLS version 1.2
    Tls12,
    /// TLS version 1.3
    Tls13,
}

/// User roles based on certificate attributes (RBAC).
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UserRole {
    /// Administrator with full access
    Admin,
    /// Trader with trading permissions
    Trader,
    /// Analyst with read/analysis permissions
    Analyst,
    /// Risk manager with risk oversight
    RiskManager,
    /// Compliance officer with audit access
    ComplianceOfficer,
    /// Read-only access
    ReadOnly,
}

impl UserRole {
    /// Get permissions for this role.
    pub fn get_permissions(&self) -> Vec<&'static str> {
        match self {
            UserRole::Admin => vec![
                "trading.submit_order",
                "trading.cancel_order",
                "trading.modify_order",
                "risk.view_positions",
                "risk.modify_limits",
                "analytics.view_data",
                "analytics.run_backtest",
                "compliance.view_reports",
                "system.configure",
            ],
            UserRole::Trader => vec![
                "trading.submit_order",
                "trading.cancel_order",
                "trading.modify_order",
                "risk.view_positions",
                "analytics.view_data",
            ],
            UserRole::Analyst => vec![
                "analytics.view_data",
                "analytics.run_backtest",
                "risk.view_positions",
            ],
            UserRole::RiskManager => vec![
                "risk.view_positions",
                "risk.modify_limits",
                "analytics.view_data",
                "compliance.view_reports",
            ],
            UserRole::ComplianceOfficer => vec![
                "compliance.view_reports",
                "analytics.view_data",
                "risk.view_positions",
            ],
            UserRole::ReadOnly => vec!["analytics.view_data"],
        }
    }
}

/// Client identity extracted from mTLS certificate.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ClientIdentity {
    /// Common Name (CN) from certificate
    pub common_name: String,
    /// Organizational Unit (OU) from certificate
    pub organizational_unit: String,
    /// Certificate serial number
    pub serial_number: String,
    /// Certificate issuer
    pub issuer: String,
}

impl ClientIdentity {
    /// Check if client is authorized for trading operations.
    pub fn is_authorized_for_trading(&self) -> bool {
        matches!(self.organizational_unit.as_str(), "trading" | "admin")
    }

    /// Check if client is authorized for read-only operations.
    pub fn is_authorized_for_readonly(&self) -> bool {
        matches!(
            self.organizational_unit.as_str(),
            "trading" | "admin" | "analytics" | "risk" | "compliance"
        )
    }

    /// Get user role based on certificate.
    pub fn get_role(&self) -> UserRole {
        match self.organizational_unit.as_str() {
            "admin" => UserRole::Admin,
            "trading" => UserRole::Trader,
            "analytics" => UserRole::Analyst,
            "risk" => UserRole::RiskManager,
            "compliance" => UserRole::ComplianceOfficer,
            _ => UserRole::ReadOnly,
        }
    }
}

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

    #[test]
    fn test_client_identity_authorization() {
        let trading_identity = ClientIdentity {
            common_name: "trader1.trading.foxhunt.internal".to_string(),
            organizational_unit: "trading".to_string(),
            serial_number: "12345".to_string(),
            issuer: "Foxhunt Trading CA".to_string(),
        };

        assert!(trading_identity.is_authorized_for_trading());
        assert!(trading_identity.is_authorized_for_readonly());
        assert_eq!(trading_identity.get_role(), UserRole::Trader);

        let readonly_identity = ClientIdentity {
            common_name: "analyst1.analytics.foxhunt.internal".to_string(),
            organizational_unit: "analytics".to_string(),
            serial_number: "12346".to_string(),
            issuer: "Foxhunt Trading CA".to_string(),
        };

        assert!(!readonly_identity.is_authorized_for_trading());
        assert!(readonly_identity.is_authorized_for_readonly());
        assert_eq!(readonly_identity.get_role(), UserRole::Analyst);
    }

    #[test]
    fn test_user_role_permissions() {
        let trader = UserRole::Trader;
        let permissions = trader.get_permissions();

        assert!(permissions.contains(&"trading.submit_order"));
        assert!(permissions.contains(&"trading.cancel_order"));
        assert!(!permissions.contains(&"system.configure"));

        let readonly = UserRole::ReadOnly;
        let readonly_permissions = readonly.get_permissions();

        assert!(!readonly_permissions.contains(&"trading.submit_order"));
        assert!(readonly_permissions.contains(&"analytics.view_data"));
    }

    #[test]
    fn test_tls_protocol_version_equality() {
        let tls13 = TlsProtocolVersion::Tls13;
        let tls12 = TlsProtocolVersion::Tls12;

        assert_ne!(tls13, tls12);
        assert_eq!(tls13, TlsProtocolVersion::Tls13);
    }
}
