use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Feature flags configuration for optional functionality
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeatureConfig {
    /// Authentication features
    pub auth: AuthFeatures,
    /// RBAC (Role-Based Access Control) features
    pub rbac: RBACFeatures,
    /// Content management features
    pub content: ContentFeatures,
    /// Security features
    pub security: SecurityFeatures,
    /// Performance features
    pub performance: PerformanceFeatures,
    /// Custom feature flags
    pub custom: HashMap<String, bool>,
}

/// Authentication feature flags
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthFeatures {
    /// Enable basic authentication
    pub enabled: bool,
    /// Enable JWT token authentication
    pub jwt: bool,
    /// Enable OAuth providers
    pub oauth: bool,
    /// Enable two-factor authentication
    pub two_factor: bool,
    /// Enable session management
    pub sessions: bool,
    /// Enable password reset functionality
    pub password_reset: bool,
    /// Enable email verification
    pub email_verification: bool,
}

/// RBAC feature flags
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RBACFeatures {
    /// Enable RBAC system
    pub enabled: bool,
    /// Enable database access control
    pub database_access: bool,
    /// Enable file access control
    pub file_access: bool,
    /// Enable content access control
    pub content_access: bool,
    /// Enable API access control
    pub api_access: bool,
    /// Enable user categories
    pub categories: bool,
    /// Enable user tags
    pub tags: bool,
    /// Enable access rule caching
    pub caching: bool,
    /// Enable audit logging
    pub audit_logging: bool,
    /// Enable TOML configuration loading
    pub toml_config: bool,
    /// Enable hierarchical permissions
    pub hierarchical_permissions: bool,
    /// Enable dynamic rule evaluation
    pub dynamic_rules: bool,
}

/// Content management feature flags
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContentFeatures {
    /// Enable content management system
    pub enabled: bool,
    /// Enable markdown rendering
    pub markdown: bool,
    /// Enable syntax highlighting
    pub syntax_highlighting: bool,
    /// Enable file uploads
    pub file_uploads: bool,
    /// Enable content versioning
    pub versioning: bool,
    /// Enable content scheduling
    pub scheduling: bool,
    /// Enable SEO features
    pub seo: bool,
}

/// Security feature flags
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityFeatures {
    /// Enable CSRF protection
    pub csrf: bool,
    /// Enable security headers
    pub security_headers: bool,
    /// Enable rate limiting
    pub rate_limiting: bool,
    /// Enable input sanitization
    pub input_sanitization: bool,
    /// Enable SQL injection protection
    pub sql_injection_protection: bool,
    /// Enable XSS protection
    pub xss_protection: bool,
    /// Enable content security policy
    pub content_security_policy: bool,
}

/// Performance feature flags
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceFeatures {
    /// Enable response caching
    pub response_caching: bool,
    /// Enable database query caching
    pub query_caching: bool,
    /// Enable compression
    pub compression: bool,
    /// Enable connection pooling
    pub connection_pooling: bool,
    /// Enable lazy loading
    pub lazy_loading: bool,
    /// Enable background tasks
    pub background_tasks: bool,
}

impl Default for FeatureConfig {
    fn default() -> Self {
        Self {
            auth: AuthFeatures::default(),
            rbac: RBACFeatures::default(),
            content: ContentFeatures::default(),
            security: SecurityFeatures::default(),
            performance: PerformanceFeatures::default(),
            custom: HashMap::new(),
        }
    }
}

impl Default for AuthFeatures {
    fn default() -> Self {
        Self {
            enabled: true,
            jwt: true,
            oauth: false,
            two_factor: false,
            sessions: true,
            password_reset: true,
            email_verification: false,
        }
    }
}

impl Default for RBACFeatures {
    fn default() -> Self {
        Self {
            enabled: false, // RBAC is optional and disabled by default
            database_access: false,
            file_access: false,
            content_access: false,
            api_access: false,
            categories: false,
            tags: false,
            caching: false,
            audit_logging: false,
            toml_config: false,
            hierarchical_permissions: false,
            dynamic_rules: false,
        }
    }
}

impl Default for ContentFeatures {
    fn default() -> Self {
        Self {
            enabled: true,
            markdown: true,
            syntax_highlighting: false,
            file_uploads: true,
            versioning: false,
            scheduling: false,
            seo: true,
        }
    }
}

impl Default for SecurityFeatures {
    fn default() -> Self {
        Self {
            csrf: true,
            security_headers: true,
            rate_limiting: true,
            input_sanitization: true,
            sql_injection_protection: true,
            xss_protection: true,
            content_security_policy: true,
        }
    }
}

impl Default for PerformanceFeatures {
    fn default() -> Self {
        Self {
            response_caching: true,
            query_caching: true,
            compression: true,
            connection_pooling: true,
            lazy_loading: false,
            background_tasks: true,
        }
    }
}

#[allow(dead_code)]
impl FeatureConfig {
    /// Create a new feature configuration with all features enabled
    pub fn all_enabled() -> Self {
        Self {
            auth: AuthFeatures {
                enabled: true,
                jwt: true,
                oauth: true,
                two_factor: true,
                sessions: true,
                password_reset: true,
                email_verification: true,
            },
            rbac: RBACFeatures {
                enabled: true,
                database_access: true,
                file_access: true,
                content_access: true,
                api_access: true,
                categories: true,
                tags: true,
                caching: true,
                audit_logging: true,
                toml_config: true,
                hierarchical_permissions: true,
                dynamic_rules: true,
            },
            content: ContentFeatures {
                enabled: true,
                markdown: true,
                syntax_highlighting: true,
                file_uploads: true,
                versioning: true,
                scheduling: true,
                seo: true,
            },
            security: SecurityFeatures {
                csrf: true,
                security_headers: true,
                rate_limiting: true,
                input_sanitization: true,
                sql_injection_protection: true,
                xss_protection: true,
                content_security_policy: true,
            },
            performance: PerformanceFeatures {
                response_caching: true,
                query_caching: true,
                compression: true,
                connection_pooling: true,
                lazy_loading: true,
                background_tasks: true,
            },
            custom: HashMap::new(),
        }
    }

    /// Create a minimal feature configuration
    pub fn minimal() -> Self {
        Self {
            auth: AuthFeatures {
                enabled: true,
                jwt: true,
                oauth: false,
                two_factor: false,
                sessions: true,
                password_reset: false,
                email_verification: false,
            },
            rbac: RBACFeatures::default(), // All disabled
            content: ContentFeatures {
                enabled: true,
                markdown: true,
                syntax_highlighting: false,
                file_uploads: false,
                versioning: false,
                scheduling: false,
                seo: false,
            },
            security: SecurityFeatures {
                csrf: true,
                security_headers: true,
                rate_limiting: false,
                input_sanitization: true,
                sql_injection_protection: true,
                xss_protection: true,
                content_security_policy: false,
            },
            performance: PerformanceFeatures {
                response_caching: false,
                query_caching: false,
                compression: false,
                connection_pooling: true,
                lazy_loading: false,
                background_tasks: false,
            },
            custom: HashMap::new(),
        }
    }

    /// Enable RBAC with default settings
    pub fn enable_rbac(&mut self) {
        self.rbac.enabled = true;
        self.rbac.database_access = true;
        self.rbac.file_access = true;
        self.rbac.content_access = true;
        self.rbac.categories = true;
        self.rbac.tags = true;
        self.rbac.caching = true;
        self.rbac.audit_logging = true;
    }

    /// Enable RBAC with all features
    pub fn enable_rbac_full(&mut self) {
        self.rbac.enabled = true;
        self.rbac.database_access = true;
        self.rbac.file_access = true;
        self.rbac.content_access = true;
        self.rbac.api_access = true;
        self.rbac.categories = true;
        self.rbac.tags = true;
        self.rbac.caching = true;
        self.rbac.audit_logging = true;
        self.rbac.toml_config = true;
        self.rbac.hierarchical_permissions = true;
        self.rbac.dynamic_rules = true;
    }

    /// Disable RBAC completely
    pub fn disable_rbac(&mut self) {
        self.rbac = RBACFeatures::default();
    }

    /// Check if RBAC is enabled
    pub fn is_rbac_enabled(&self) -> bool {
        self.rbac.enabled
    }

    /// Check if a specific RBAC feature is enabled
    pub fn is_rbac_feature_enabled(&self, feature: &str) -> bool {
        if !self.rbac.enabled {
            return false;
        }

        match feature {
            "database_access" => self.rbac.database_access,
            "file_access" => self.rbac.file_access,
            "content_access" => self.rbac.content_access,
            "api_access" => self.rbac.api_access,
            "categories" => self.rbac.categories,
            "tags" => self.rbac.tags,
            "caching" => self.rbac.caching,
            "audit_logging" => self.rbac.audit_logging,
            "toml_config" => self.rbac.toml_config,
            "hierarchical_permissions" => self.rbac.hierarchical_permissions,
            "dynamic_rules" => self.rbac.dynamic_rules,
            _ => false,
        }
    }

    /// Get a custom feature flag
    pub fn get_custom_feature(&self, key: &str) -> Option<bool> {
        self.custom.get(key).copied()
    }

    /// Set a custom feature flag
    pub fn set_custom_feature(&mut self, key: String, value: bool) {
        self.custom.insert(key, value);
    }

    /// Load feature configuration from environment variables
    pub fn from_env() -> Self {
        let mut config = Self::default();

        // Auth features
        if let Ok(val) = std::env::var("ENABLE_AUTH") {
            config.auth.enabled = val.parse().unwrap_or(true);
        }
        if let Ok(val) = std::env::var("ENABLE_JWT") {
            config.auth.jwt = val.parse().unwrap_or(true);
        }
        if let Ok(val) = std::env::var("ENABLE_OAUTH") {
            config.auth.oauth = val.parse().unwrap_or(false);
        }
        if let Ok(val) = std::env::var("ENABLE_2FA") {
            config.auth.two_factor = val.parse().unwrap_or(false);
        }

        // RBAC features
        if let Ok(val) = std::env::var("ENABLE_RBAC") {
            config.rbac.enabled = val.parse().unwrap_or(false);
        }
        if let Ok(val) = std::env::var("ENABLE_RBAC_DATABASE") {
            config.rbac.database_access = val.parse().unwrap_or(false);
        }
        if let Ok(val) = std::env::var("ENABLE_RBAC_FILES") {
            config.rbac.file_access = val.parse().unwrap_or(false);
        }
        if let Ok(val) = std::env::var("ENABLE_RBAC_CONTENT") {
            config.rbac.content_access = val.parse().unwrap_or(false);
        }
        if let Ok(val) = std::env::var("ENABLE_RBAC_CATEGORIES") {
            config.rbac.categories = val.parse().unwrap_or(false);
        }
        if let Ok(val) = std::env::var("ENABLE_RBAC_TAGS") {
            config.rbac.tags = val.parse().unwrap_or(false);
        }
        if let Ok(val) = std::env::var("ENABLE_RBAC_CACHING") {
            config.rbac.caching = val.parse().unwrap_or(false);
        }
        if let Ok(val) = std::env::var("ENABLE_RBAC_AUDIT") {
            config.rbac.audit_logging = val.parse().unwrap_or(false);
        }

        // Content features
        if let Ok(val) = std::env::var("ENABLE_CONTENT") {
            config.content.enabled = val.parse().unwrap_or(true);
        }
        if let Ok(val) = std::env::var("ENABLE_MARKDOWN") {
            config.content.markdown = val.parse().unwrap_or(true);
        }
        if let Ok(val) = std::env::var("ENABLE_FILE_UPLOADS") {
            config.content.file_uploads = val.parse().unwrap_or(true);
        }

        // Security features
        if let Ok(val) = std::env::var("ENABLE_CSRF") {
            config.security.csrf = val.parse().unwrap_or(true);
        }
        if let Ok(val) = std::env::var("ENABLE_RATE_LIMITING") {
            config.security.rate_limiting = val.parse().unwrap_or(true);
        }

        // Performance features
        if let Ok(val) = std::env::var("ENABLE_CACHING") {
            config.performance.response_caching = val.parse().unwrap_or(true);
        }
        if let Ok(val) = std::env::var("ENABLE_COMPRESSION") {
            config.performance.compression = val.parse().unwrap_or(true);
        }

        config
    }

    /// Convert to environment variables format
    pub fn to_env_vars(&self) -> Vec<(String, String)> {
        let mut vars = Vec::new();

        // Auth features
        vars.push(("ENABLE_AUTH".to_string(), self.auth.enabled.to_string()));
        vars.push(("ENABLE_JWT".to_string(), self.auth.jwt.to_string()));
        vars.push(("ENABLE_OAUTH".to_string(), self.auth.oauth.to_string()));
        vars.push(("ENABLE_2FA".to_string(), self.auth.two_factor.to_string()));

        // RBAC features
        vars.push(("ENABLE_RBAC".to_string(), self.rbac.enabled.to_string()));
        vars.push((
            "ENABLE_RBAC_DATABASE".to_string(),
            self.rbac.database_access.to_string(),
        ));
        vars.push((
            "ENABLE_RBAC_FILES".to_string(),
            self.rbac.file_access.to_string(),
        ));
        vars.push((
            "ENABLE_RBAC_CONTENT".to_string(),
            self.rbac.content_access.to_string(),
        ));
        vars.push((
            "ENABLE_RBAC_CATEGORIES".to_string(),
            self.rbac.categories.to_string(),
        ));
        vars.push(("ENABLE_RBAC_TAGS".to_string(), self.rbac.tags.to_string()));
        vars.push((
            "ENABLE_RBAC_CACHING".to_string(),
            self.rbac.caching.to_string(),
        ));
        vars.push((
            "ENABLE_RBAC_AUDIT".to_string(),
            self.rbac.audit_logging.to_string(),
        ));

        // Content features
        vars.push((
            "ENABLE_CONTENT".to_string(),
            self.content.enabled.to_string(),
        ));
        vars.push((
            "ENABLE_MARKDOWN".to_string(),
            self.content.markdown.to_string(),
        ));
        vars.push((
            "ENABLE_FILE_UPLOADS".to_string(),
            self.content.file_uploads.to_string(),
        ));

        // Security features
        vars.push(("ENABLE_CSRF".to_string(), self.security.csrf.to_string()));
        vars.push((
            "ENABLE_RATE_LIMITING".to_string(),
            self.security.rate_limiting.to_string(),
        ));

        // Performance features
        vars.push((
            "ENABLE_CACHING".to_string(),
            self.performance.response_caching.to_string(),
        ));
        vars.push((
            "ENABLE_COMPRESSION".to_string(),
            self.performance.compression.to_string(),
        ));

        vars
    }

    /// Validate feature configuration
    pub fn validate(&self) -> Result<(), String> {
        // Check for conflicting configurations
        if self.rbac.enabled && !self.auth.enabled {
            return Err("RBAC requires authentication to be enabled".to_string());
        }

        if self.rbac.categories && !self.rbac.enabled {
            return Err("RBAC categories require RBAC to be enabled".to_string());
        }

        if self.rbac.tags && !self.rbac.enabled {
            return Err("RBAC tags require RBAC to be enabled".to_string());
        }

        if self.rbac.audit_logging && !self.rbac.enabled {
            return Err("RBAC audit logging requires RBAC to be enabled".to_string());
        }

        if self.auth.two_factor && !self.auth.enabled {
            return Err(
                "Two-factor authentication requires authentication to be enabled".to_string(),
            );
        }

        if self.auth.oauth && !self.auth.enabled {
            return Err("OAuth requires authentication to be enabled".to_string());
        }

        Ok(())
    }
}

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

    #[test]
    fn test_default_config() {
        let config = FeatureConfig::default();
        assert!(config.auth.enabled);
        assert!(!config.rbac.enabled); // RBAC should be disabled by default
        assert!(config.content.enabled);
        assert!(config.security.csrf);
        assert!(config.performance.response_caching);
    }

    #[test]
    fn test_all_enabled_config() {
        let config = FeatureConfig::all_enabled();
        assert!(config.auth.enabled);
        assert!(config.rbac.enabled);
        assert!(config.rbac.database_access);
        assert!(config.rbac.categories);
        assert!(config.rbac.tags);
        assert!(config.content.enabled);
        assert!(config.security.csrf);
        assert!(config.performance.response_caching);
    }

    #[test]
    fn test_minimal_config() {
        let config = FeatureConfig::minimal();
        assert!(config.auth.enabled);
        assert!(!config.rbac.enabled);
        assert!(!config.auth.oauth);
        assert!(!config.auth.two_factor);
        assert!(config.content.enabled);
        assert!(!config.content.file_uploads);
    }

    #[test]
    fn test_enable_rbac() {
        let mut config = FeatureConfig::default();
        assert!(!config.rbac.enabled);

        config.enable_rbac();
        assert!(config.rbac.enabled);
        assert!(config.rbac.database_access);
        assert!(config.rbac.categories);
        assert!(config.rbac.tags);
    }

    #[test]
    fn test_rbac_feature_check() {
        let mut config = FeatureConfig::default();
        assert!(!config.is_rbac_feature_enabled("database_access"));

        config.enable_rbac();
        assert!(config.is_rbac_feature_enabled("database_access"));
        assert!(config.is_rbac_feature_enabled("categories"));
        assert!(!config.is_rbac_feature_enabled("api_access")); // Not enabled in basic RBAC
    }

    #[test]
    fn test_custom_features() {
        let mut config = FeatureConfig::default();
        assert_eq!(config.get_custom_feature("my_feature"), None);

        config.set_custom_feature("my_feature".to_string(), true);
        assert_eq!(config.get_custom_feature("my_feature"), Some(true));
    }

    #[test]
    fn test_validation() {
        let mut config = FeatureConfig::default();
        config.auth.enabled = false;
        config.rbac.enabled = true;

        assert!(config.validate().is_err());

        config.auth.enabled = true;
        assert!(config.validate().is_ok());
    }

    #[test]
    fn test_env_vars() {
        let config = FeatureConfig::default();
        let env_vars = config.to_env_vars();

        assert!(
            env_vars
                .iter()
                .any(|(k, v)| k == "ENABLE_AUTH" && v == "true")
        );
        assert!(
            env_vars
                .iter()
                .any(|(k, v)| k == "ENABLE_RBAC" && v == "false")
        );
    }
}
