//! Configuration for the sync layer.

use std::time::Duration;

/// Configuration for sync operations.
#[derive(Debug, Clone)]
pub struct SyncConfig {
    /// List of peer addresses to sync with (e.g., "http://peer:18182").
    pub peers: Vec<String>,

    /// Enable gossip broadcast to peers.
    pub gossip_enabled: bool,

    /// Timeout for gossip operations.
    pub gossip_timeout: Duration,

    /// Interval between anti-entropy sync cycles.
    pub anti_entropy_interval: Duration,

    /// Interval between Merkle tree checkpoints.
    pub checkpoint_interval: Duration,

    /// Maximum concurrent connections per peer.
    pub max_connections_per_peer: usize,

    /// Maximum hashes to fetch in a single request.
    pub max_fetch_batch_size: usize,

    /// Fanout for gossip (number of peers to send to).
    pub gossip_fanout: usize,
}

impl Default for SyncConfig {
    fn default() -> Self {
        Self {
            peers: Vec::new(),
            gossip_enabled: true,
            gossip_timeout: Duration::from_secs(5),
            anti_entropy_interval: Duration::from_secs(60),
            checkpoint_interval: Duration::from_secs(300), // 5 minutes
            max_connections_per_peer: 4,
            max_fetch_batch_size: 1000,
            gossip_fanout: 3,
        }
    }
}

impl SyncConfig {
    /// Create a new default configuration.
    pub fn new() -> Self {
        Self::default()
    }

    /// Add a peer address.
    #[must_use]
    pub fn with_peer(mut self, addr: impl Into<String>) -> Self {
        self.peers.push(addr.into());
        self
    }

    /// Set multiple peer addresses.
    #[must_use]
    pub fn with_peers(mut self, addrs: Vec<String>) -> Self {
        self.peers = addrs;
        self
    }

    /// Enable or disable gossip.
    #[must_use]
    pub fn with_gossip_enabled(mut self, enabled: bool) -> Self {
        self.gossip_enabled = enabled;
        self
    }

    /// Set the gossip timeout.
    #[must_use]
    pub fn with_gossip_timeout(mut self, timeout: Duration) -> Self {
        self.gossip_timeout = timeout;
        self
    }

    /// Set the anti-entropy interval.
    #[must_use]
    pub fn with_anti_entropy_interval(mut self, interval: Duration) -> Self {
        self.anti_entropy_interval = interval;
        self
    }

    /// Set the checkpoint interval.
    #[must_use]
    pub fn with_checkpoint_interval(mut self, interval: Duration) -> Self {
        self.checkpoint_interval = interval;
        self
    }

    /// Set the gossip fanout.
    #[must_use]
    pub fn with_gossip_fanout(mut self, fanout: usize) -> Self {
        self.gossip_fanout = fanout;
        self
    }
}

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

    #[test]
    fn test_default_config() {
        let config = SyncConfig::default();
        assert!(config.peers.is_empty());
        assert!(config.gossip_enabled);
        assert_eq!(config.gossip_timeout, Duration::from_secs(5));
        assert_eq!(config.anti_entropy_interval, Duration::from_secs(60));
    }

    #[test]
    fn test_builder() {
        let config = SyncConfig::new()
            .with_peer("http://peer1:18182")
            .with_peer("http://peer2:18182")
            .with_gossip_enabled(false)
            .with_gossip_fanout(2);

        assert_eq!(config.peers.len(), 2);
        assert!(!config.gossip_enabled);
        assert_eq!(config.gossip_fanout, 2);
    }
}
