use std::time::Duration;

use crate::error::{Result, RuntimeError};

/// Where the runtime is running; affects whether automatic pulls are allowed.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RuntimeMode {
    Development,
    Production,
}

/// Authentication for HTTP(S) requests to the Ollama API.
#[derive(Debug, Clone)]
pub enum AuthConfig {
    BearerToken(String),
    Basic { username: String, password: String },
    CustomHeader { key: String, value: String },
}

/// Configuration for [`crate::runtime::OllamaRuntime`].
#[derive(Debug, Clone)]
pub struct RuntimeConfig {
    pub base_url: String,
    pub timeout: Duration,
    pub connect_timeout: Duration,
    pub max_retries: usize,
    pub max_concurrent: usize,
    pub auto_pull: bool,
    pub mode: RuntimeMode,
    pub auth: Option<AuthConfig>,
}

impl RuntimeConfig {
    /// Returns `Err` when the configuration violates safety rules (for example,
    /// `Production` with `auto_pull` enabled) or when limits are unusable.
    pub fn validate(&self) -> Result<()> {
        if self.mode == RuntimeMode::Production && self.auto_pull {
            return Err(RuntimeError::Other(
                "auto_pull must be disabled in Production mode".into(),
            ));
        }
        if self.max_concurrent == 0 {
            return Err(RuntimeError::Other(
                "max_concurrent must be at least 1".into(),
            ));
        }
        Ok(())
    }
}

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

    #[test]
    fn rejects_production_with_auto_pull() {
        let cfg = RuntimeConfig {
            base_url: "http://127.0.0.1:11434".into(),
            timeout: Duration::from_secs(1),
            connect_timeout: Duration::from_secs(1),
            max_retries: 0,
            max_concurrent: 1,
            auto_pull: true,
            mode: RuntimeMode::Production,
            auth: None,
        };
        assert!(cfg.validate().is_err());
    }
}
