#![deny(clippy::unwrap_used, clippy::expect_used)]
#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used))]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(missing_debug_implementations)]
#![allow(unused_crate_dependencies)]
#![allow(clippy::float_arithmetic)]
#![allow(clippy::non_ascii_literal)]
#![allow(clippy::str_to_string)]
#![allow(clippy::partial_pub_fields)]
#![allow(clippy::multiple_inherent_impl)]
#![allow(clippy::same_name_method)]
#![allow(clippy::shadow_reuse)]
#![allow(clippy::shadow_unrelated)]
#![allow(clippy::shadow_same)]
#![allow(clippy::doc_markdown)]
#![allow(clippy::indexing_slicing)]
#![allow(clippy::missing_const_for_fn)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::integer_division)]
#![allow(clippy::cognitive_complexity)]
#![allow(clippy::similar_names)]
#![allow(clippy::clone_on_ref_ptr)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::as_conversions)]
#![allow(clippy::cast_precision_loss)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::default_numeric_fallback)]
#![allow(clippy::arithmetic_side_effects)]
#![allow(clippy::needless_range_loop)]
#![allow(clippy::into_iter_on_ref)]
#![allow(clippy::new_without_default)]
#![allow(clippy::manual_let_else)]
#![allow(clippy::unnecessary_wraps)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::must_use_candidate)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::cast_sign_loss)]
#![allow(clippy::cast_possible_wrap)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::unused_async)]
#![allow(clippy::match_same_arms)]
#![allow(clippy::unused_self)]
#![allow(clippy::map_err_ignore)]
#![allow(clippy::single_match_else)]
#![allow(clippy::wildcard_imports)]
#![allow(clippy::unnecessary_cast)]

//! ML Security Module
//!
//! Provides comprehensive security features for ML inference:
//! - Prediction validation and model poisoning detection
//! - Ensemble anomaly detection
//! - Security event logging
//!
//! # Architecture
//!
//! ```text
//! ┌──────────────────┐      ┌──────────────────┐
//! │   Prediction     │      │    Ensemble      │
//! │   Validator      │──────│    Anomaly       │
//! │                  │      │    Detector      │
//! └────────┬─────────┘      └────────┬─────────┘
//!          │                         │
//!          └─────────┬───────────────┘
//!                    │
//!                    ▼
//!          ┌──────────────────┐
//!          │  Security Event  │
//!          │     Logger       │
//!          └──────────────────┘
//! ```

pub mod anomaly_detector;
pub mod prediction_validator;

pub use anomaly_detector::{
    Anomaly, AnomalyDetectorConfig, AnomalyReport, AnomalySeverity, DetectorStatistics,
    EnsembleAnomalyDetector,
};
pub use prediction_validator::{
    PredictionStats, PredictionValidator, ValidatedPrediction, ValidationConfig, ValidationFlag,
};

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

/// Security event types for ML system
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SecurityEventType {
    // Checkpoint security
    CheckpointSignatureFailure,
    CheckpointSignatureMissing,
    CheckpointTamperingDetected,

    // Prediction validation
    PredictionOutlierDetected,
    PredictionOutOfBounds,
    ExtremeRateExceeded,

    // Ensemble anomalies
    EnsembleSuddenShift,
    CoordinatedAttackSuspected,
    ModelBehavioralDrift,

    // System events
    AutomaticRollback,
    ManualIntervention,
}

/// Security event for logging
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityEvent {
    /// Event type
    pub event_type: SecurityEventType,

    /// Severity level
    pub severity: SecuritySeverity,

    /// Event timestamp
    pub timestamp: DateTime<Utc>,

    /// Model ID (if applicable)
    pub model_id: Option<String>,

    /// Checkpoint ID (if applicable)
    pub checkpoint_id: Option<String>,

    /// Prediction ID (if applicable)
    pub prediction_id: Option<String>,

    /// Human-readable description
    pub description: String,

    /// Additional metadata
    pub metadata: serde_json::Value,

    /// Action taken in response
    pub action_taken: Option<String>,
}

/// Security severity levels
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum SecuritySeverity {
    Low,
    Medium,
    High,
    Critical,
}

impl SecurityEvent {
    /// Create a new security event
    pub fn new(
        event_type: SecurityEventType,
        severity: SecuritySeverity,
        description: String,
    ) -> Self {
        Self {
            event_type,
            severity,
            timestamp: Utc::now(),
            model_id: None,
            checkpoint_id: None,
            prediction_id: None,
            description,
            metadata: serde_json::Value::Null,
            action_taken: None,
        }
    }

    /// Set model ID
    pub fn with_model_id(mut self, model_id: String) -> Self {
        self.model_id = Some(model_id);
        self
    }

    /// Set checkpoint ID
    pub fn with_checkpoint_id(mut self, checkpoint_id: String) -> Self {
        self.checkpoint_id = Some(checkpoint_id);
        self
    }

    /// Set prediction ID
    pub fn with_prediction_id(mut self, prediction_id: String) -> Self {
        self.prediction_id = Some(prediction_id);
        self
    }

    /// Set metadata
    pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
        self.metadata = metadata;
        self
    }

    /// Set action taken
    pub fn with_action(mut self, action: String) -> Self {
        self.action_taken = Some(action);
        self
    }
}

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

    #[test]
    fn test_security_event_builder() {
        let event = SecurityEvent::new(
            SecurityEventType::PredictionOutlierDetected,
            SecuritySeverity::Medium,
            "Test outlier detection".to_owned(),
        )
        .with_model_id("DQN".to_owned())
        .with_action("Flagged for review".to_owned());

        assert_eq!(event.severity, SecuritySeverity::Medium);
        assert_eq!(event.model_id, Some("DQN".to_owned()));
        assert_eq!(event.action_taken, Some("Flagged for review".to_owned()));
    }

    #[test]
    fn test_severity_ordering() {
        assert!(SecuritySeverity::Critical > SecuritySeverity::High);
        assert!(SecuritySeverity::High > SecuritySeverity::Medium);
        assert!(SecuritySeverity::Medium > SecuritySeverity::Low);
    }
}
