//! Configuration options for reactive configuration.

use crate::constants::{DEFAULT_BUFFER_SIZE, DEFAULT_DEBOUNCE_MS, MAX_RETRIES};

/// Configuration options for the reactive system.
#[derive(Debug, Clone)]
pub struct ConfigOptions {
    /// Debounce time in milliseconds for file watching.
    pub debounce_ms: u64,
    /// Buffer size for event channels.
    pub buffer_size: usize,
    /// Maximum retry attempts for failed operations.
    pub max_retries: usize,
    /// Enable async mode.
    pub async_mode: bool,
    /// Enable file watching.
    pub watch_enabled: bool,
}

impl ConfigOptions {
    /// Create new configuration options with defaults.
    #[must_use]
    pub const fn new() -> Self {
        Self {
            debounce_ms: DEFAULT_DEBOUNCE_MS,
            buffer_size: DEFAULT_BUFFER_SIZE,
            max_retries: MAX_RETRIES,
            async_mode: cfg!(feature = "async"),
            watch_enabled: cfg!(feature = "watch"),
        }
    }

    /// Set the debounce time in milliseconds.
    #[must_use]
    pub const fn debounce_ms(mut self, ms: u64) -> Self {
        self.debounce_ms = ms;
        self
    }

    /// Set the buffer size for event channels.
    #[must_use]
    pub const fn buffer_size(mut self, size: usize) -> Self {
        self.buffer_size = size;
        self
    }

    /// Set the maximum retry attempts.
    #[must_use]
    pub const fn max_retries(mut self, retries: usize) -> Self {
        self.max_retries = retries;
        self
    }

    /// Enable or disable async mode.
    #[must_use]
    pub const fn async_mode(mut self, enabled: bool) -> Self {
        self.async_mode = enabled;
        self
    }

    /// Enable or disable file watching.
    #[must_use]
    pub const fn watch_enabled(mut self, enabled: bool) -> Self {
        self.watch_enabled = enabled;
        self
    }

    /// Build the configuration options.
    #[must_use]
    pub const fn build(self) -> Self {
        self
    }
}

impl Default for ConfigOptions {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::constants::{DEFAULT_BUFFER_SIZE, DEFAULT_DEBOUNCE_MS, MAX_RETRIES};

    #[test]
    fn test_config_options_default_values() {
        let options = ConfigOptions::new();

        assert_eq!(options.debounce_ms, DEFAULT_DEBOUNCE_MS);
        assert_eq!(options.buffer_size, DEFAULT_BUFFER_SIZE);
        assert_eq!(options.max_retries, MAX_RETRIES);
        assert_eq!(options.async_mode, cfg!(feature = "async"));
        assert_eq!(options.watch_enabled, cfg!(feature = "watch"));
    }

    #[test]
    fn test_config_options_builder_methods() {
        let options = ConfigOptions::new()
            .debounce_ms(250)
            .buffer_size(64)
            .max_retries(7)
            .async_mode(false)
            .watch_enabled(false)
            .build();

        assert_eq!(options.debounce_ms, 250);
        assert_eq!(options.buffer_size, 64);
        assert_eq!(options.max_retries, 7);
        assert!(!options.async_mode);
        assert!(!options.watch_enabled);
    }

    #[test]
    fn test_config_options_default_impl_matches_new() {
        let options = ConfigOptions::default();

        assert_eq!(options.debounce_ms, ConfigOptions::new().debounce_ms);
        assert_eq!(options.buffer_size, ConfigOptions::new().buffer_size);
        assert_eq!(options.max_retries, ConfigOptions::new().max_retries);
    }
}
