//! Audit persistence contracts and reference implementations.

use crate::models::AuditEvent;
use std::io;

/// Audit persistence is supplied by the host so durability and tamper resistance are
/// explicit deployment choices rather than implied by a local file helper.
pub trait AuditSink: Send + Sync {
    /// Persists one authorization decision before the caller executes an allowed operation.
    fn write_event(&self, event: &AuditEvent) -> io::Result<()>;
}

impl AuditSink for VecAuditSink {
    fn write_event(&self, event: &AuditEvent) -> io::Result<()> {
        self.events
            .lock()
            .map_err(|_| io::Error::other("audit sink lock poisoned"))?
            .push(event.clone());
        Ok(())
    }
}

/// Small test/reference sink. It is not a production durability mechanism.
#[derive(Default)]
pub struct VecAuditSink {
    events: std::sync::Mutex<Vec<AuditEvent>>,
}

impl VecAuditSink {
    /// Creates an empty in-memory audit sink.
    pub fn new() -> Self {
        Self::default()
    }

    /// Returns a snapshot of all recorded events in insertion order.
    pub fn events(&self) -> io::Result<Vec<AuditEvent>> {
        Ok(self
            .events
            .lock()
            .map_err(|_| io::Error::other("audit sink lock poisoned"))?
            .clone())
    }
}
