use super::{errors::ConfigError, CipherStashConfigFile, CipherStashSecretConfigFile};
use std::{
    fs::File,
    io::{BufWriter, Write},
};

/// Writes the docker env file usually named `.env.proxy.docker`.
///
/// # Example
///
/// ```env
/// CS_AUTH__WORKSPACE_ID=IJELRKEREPW...
/// CS_ENCRYPT__CLIENT_ID=774c6c47-c0f3-d442-...
/// CS_ENCRYPT__DATASET_ID=56d980dc-68f5-fc44-...
/// CS_LOG__FORMAT=pretty
/// CS_ENCRYPT__CLIENT_KEY=a4627903070770325f...
/// CS_AUTH__CLIENT_ACCESS_KEY=CSAKJC3CTYTYWYO...
/// ```
///

#[derive(Debug)]
pub struct DockerEnvFile {
    /// regular config which would normally be saved in cipherstash.toml
    regular: CipherStashConfigFile,
    /// secret config which would normally be saved in cipherstash.secret.toml
    secret: CipherStashSecretConfigFile,
}

impl DockerEnvFile {
    pub const DEFAULT_FILE_NAME: &str = ".env.proxy.docker";

    pub fn new(regular: CipherStashConfigFile, secret: CipherStashSecretConfigFile) -> Self {
        Self { regular, secret }
    }

    /// Save the configuration to the env file to be loaded in docker-compose
    pub fn persist(
        self,
        file_path: impl AsRef<std::path::Path> + Clone,
    ) -> Result<(), ConfigError> {
        let mut writer = BufWriter::new(File::create(&file_path).map_err(ConfigError::invalid)?);

        self.regular
            .env_data()?
            .iter()
            .chain(self.secret.env_data()?.iter())
            .map(|(key, value)| format!("{key}={value}"))
            .try_for_each(|line| {
                writeln!(&mut writer, "{line}").map_err(|e| ConfigError::io(&e, file_path.clone()))
            })?;

        writer.flush().map_err(|e| ConfigError::io(&e, file_path))
    }
}
