//! Access Control Matrix
//!
//! Implements access control verification and role-based access control (RBAC).

use std::collections::HashMap;

use anyhow::Result;
use serde::{Deserialize, Serialize};

pub struct AccessControlMatrix {
    config: AccessControlConfig,
    roles: HashMap<String, Vec<String>>,
}

impl AccessControlMatrix {
    pub async fn new(config: AccessControlConfig) -> Result<Self> {
        let mut roles = HashMap::new();

        // Default roles
        roles.insert("admin".to_string(), vec!["*".to_string()]);
        roles.insert(
            "operator".to_string(),
            vec![
                "server:*".to_string(),
                "taskserv:read".to_string(),
                "cluster:read".to_string(),
            ],
        );
        roles.insert(
            "viewer".to_string(),
            vec![
                "server:read".to_string(),
                "taskserv:read".to_string(),
                "cluster:read".to_string(),
            ],
        );

        Ok(Self { config, roles })
    }

    pub fn check_permission(&self, role: &str, permission: &str) -> bool {
        if let Some(permissions) = self.roles.get(role) {
            permissions
                .iter()
                .any(|p| p == "*" || p == permission || permission.starts_with(&p.replace("*", "")))
        } else {
            false
        }
    }

    pub fn get_role_permissions(&self, role: &str) -> Vec<String> {
        self.roles.get(role).cloned().unwrap_or_default()
    }

    pub fn list_roles(&self) -> Vec<String> {
        self.roles.keys().cloned().collect()
    }

    pub async fn health_check(&self) -> Result<()> {
        Ok(())
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccessControlConfig {
    pub enable_rbac: bool,
    pub require_mfa_for_admin: bool,
    pub session_timeout_seconds: u64,
}

impl Default for AccessControlConfig {
    fn default() -> Self {
        Self {
            enable_rbac: true,
            require_mfa_for_admin: true,
            session_timeout_seconds: 3600,
        }
    }
}
