use std::time::Duration;

/// Top-level configuration for [`crate::MonkClient`].
#[derive(Debug, Clone)]
pub struct ClientConfig {
    pub base_url: String,
    pub api_key: String,
    pub timeout: Duration,
    pub retry: RetryConfig,
    pub buffer: BufferConfig,
}

/// Controls retry behaviour: exponential backoff, jitter, circuit breaker.
#[derive(Debug, Clone)]
pub struct RetryConfig {
    /// Initial backoff delay before the first retry.
    pub base_delay: Duration,
    /// Upper bound on any single backoff sleep.
    pub max_delay: Duration,
    /// Maximum number of retry attempts (0 = no retries, fire once).
    pub max_retries: u32,
    /// Optional hard deadline for the entire operation (including all retries).
    /// `None` means no deadline — retries are only bounded by `max_retries`.
    pub deadline: Option<Duration>,
    /// Consecutive failures before the circuit breaker opens.
    pub circuit_breaker_threshold: u32,
    /// How long the circuit stays open before allowing a probe request.
    pub circuit_breaker_cooldown: Duration,
}

impl Default for RetryConfig {
    fn default() -> Self {
        Self {
            base_delay: Duration::from_millis(100),
            max_delay: Duration::from_secs(30),
            max_retries: 5,
            deadline: Some(Duration::from_secs(120)),
            circuit_breaker_threshold: 10,
            circuit_breaker_cooldown: Duration::from_secs(30),
        }
    }
}

/// Strategy applied when the in-memory event buffer is full.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum BackpressureStrategy {
    /// Return [`crate::MonkError::BufferFull`] immediately (default).
    #[default]
    FailFast,
    /// Block the caller until space is available in the buffer.
    Block,
}

/// Controls the in-memory event buffer used by [`crate::MonkClient::ingest_buffered`].
#[derive(Debug, Clone)]
pub struct BufferConfig {
    /// Maximum events the channel can hold before back-pressure.
    pub capacity: usize,
    /// Maximum events sent per batch flush.
    pub max_batch_size: usize,
    /// Time between automatic flushes.
    pub flush_interval: Duration,
    /// Number of batch HTTP requests that can be in-flight concurrently (default 4).
    pub max_concurrent_flushes: usize,
    /// What to do when the buffer is full (default [`BackpressureStrategy::FailFast`]).
    pub backpressure: BackpressureStrategy,
}

impl Default for BufferConfig {
    fn default() -> Self {
        Self {
            capacity: 10_000,
            max_batch_size: 10_000,
            flush_interval: Duration::from_millis(500),
            max_concurrent_flushes: 4,
            backpressure: BackpressureStrategy::default(),
        }
    }
}
