//! Role Definitions
//!
//! Defines all available roles in the RBAC system

use serde::{Deserialize, Serialize};

/// Available roles in the system
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Role {
    /// Full access to all resources and actions
    Admin,

    /// Deploy and manage infrastructure
    Operator,

    /// Read infrastructure, deploy to dev
    Developer,

    /// Read-only access
    Viewer,

    /// Service account for CI/CD pipelines
    ServiceAccount,

    /// View audit logs and compliance reports
    Auditor,
}

impl Role {
    /// Get role name as string
    pub fn as_str(&self) -> &'static str {
        match self {
            Role::Admin => "admin",
            Role::Operator => "operator",
            Role::Developer => "developer",
            Role::Viewer => "viewer",
            Role::ServiceAccount => "service_account",
            Role::Auditor => "auditor",
        }
    }

    /// Parse role from string
    pub fn from_str(s: &str) -> Option<Self> {
        match s.to_lowercase().as_str() {
            "admin" => Some(Role::Admin),
            "operator" => Some(Role::Operator),
            "developer" => Some(Role::Developer),
            "viewer" => Some(Role::Viewer),
            "service_account" | "service" => Some(Role::ServiceAccount),
            "auditor" => Some(Role::Auditor),
            _ => None,
        }
    }

    /// Get role description
    pub fn description(&self) -> &'static str {
        match self {
            Role::Admin => "Full access to all resources and actions",
            Role::Operator => "Deploy and manage infrastructure",
            Role::Developer => "Read infrastructure, deploy to development",
            Role::Viewer => "Read-only access to all resources",
            Role::ServiceAccount => "Service account for automation and CI/CD",
            Role::Auditor => "View audit logs and compliance reports",
        }
    }

    /// Get role permissions level (higher = more permissions)
    pub fn permission_level(&self) -> u8 {
        match self {
            Role::Admin => 100,
            Role::Operator => 80,
            Role::Developer => 60,
            Role::ServiceAccount => 50,
            Role::Auditor => 40,
            Role::Viewer => 20,
        }
    }

    /// Check if this role can perform an action that requires a specific level
    pub fn can_perform(&self, required_level: u8) -> bool {
        self.permission_level() >= required_level
    }

    /// Get all available roles
    pub fn all_roles() -> Vec<Role> {
        vec![
            Role::Admin,
            Role::Operator,
            Role::Developer,
            Role::Viewer,
            Role::ServiceAccount,
            Role::Auditor,
        ]
    }
}

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

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

    #[test]
    fn test_role_parsing() {
        assert_eq!(Role::from_str("admin"), Some(Role::Admin));
        assert_eq!(Role::from_str("OPERATOR"), Some(Role::Operator));
        assert_eq!(Role::from_str("service"), Some(Role::ServiceAccount));
        assert_eq!(Role::from_str("invalid"), None);
    }

    #[test]
    fn test_permission_levels() {
        assert!(Role::Admin.can_perform(100));
        assert!(Role::Operator.can_perform(80));
        assert!(!Role::Viewer.can_perform(80));
    }
}
