//! Audit trail generation for policy evaluations.
//!
//! Creates structured audit entries with timestamps and SQL hashing
//! for compliance and logging purposes.

use super::types::AuditEntry;
use chrono::Utc;
use sha2::{Digest, Sha256};

/// Create an audit entry for a policy evaluation.
///
/// The `sql_hash` is the first 16 hex characters of the SHA-256 hash
/// of the SQL query, providing a compact identifier without storing
/// the full query text.
pub fn create_audit_entry(
    sql: &str,
    allowed: bool,
    violations: usize,
    warnings: usize,
    policies: usize,
    time_ms: u64,
) -> AuditEntry {
    let mut hasher = Sha256::new();
    hasher.update(sql.as_bytes());
    let hash_bytes = hasher.finalize();
    let full_hex = format!("{hash_bytes:x}");
    let sql_hash = full_hex[..16].to_string();

    AuditEntry {
        timestamp: Utc::now().format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string(),
        sql_hash,
        allowed,
        violation_count: violations,
        warning_count: warnings,
        policies_checked: policies,
        evaluation_time_ms: time_ms,
    }
}

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

    #[test]
    fn test_audit_entry_creation() {
        let entry = create_audit_entry("SELECT 1", true, 0, 0, 5, 10);
        assert!(entry.allowed);
        assert_eq!(entry.violation_count, 0);
        assert_eq!(entry.warning_count, 0);
        assert_eq!(entry.policies_checked, 5);
        assert_eq!(entry.evaluation_time_ms, 10);
        assert_eq!(entry.sql_hash.len(), 16);
        assert!(!entry.timestamp.is_empty());
    }

    #[test]
    fn test_sql_hash_is_deterministic() {
        let entry1 = create_audit_entry("SELECT * FROM users", true, 0, 0, 1, 1);
        let entry2 = create_audit_entry("SELECT * FROM users", true, 0, 0, 1, 1);
        assert_eq!(entry1.sql_hash, entry2.sql_hash);
    }

    #[test]
    fn test_different_sql_different_hash() {
        let entry1 = create_audit_entry("SELECT * FROM users", true, 0, 0, 1, 1);
        let entry2 = create_audit_entry("SELECT * FROM orders", true, 0, 0, 1, 1);
        assert_ne!(entry1.sql_hash, entry2.sql_hash);
    }
}
