use std::io::{self, IsTerminal, Read};
use crate::cli::output;
use crate::cli::{load_keyfile, prompt_password_for_vault, vault_path, Cli};
use crate::errors::Result;
use crate::vault::VaultStore;
pub fn execute(cli: &Cli, key: &str, value: Option<&str>, force: bool) -> Result<()> {
let path = vault_path(cli)?;
let secret_value = if let Some(v) = value {
if !force {
output::warning("Value provided on command line — it may appear in shell history.");
}
v.to_string()
} else if !io::stdin().is_terminal() {
let mut buf = String::new();
io::stdin().read_to_string(&mut buf)?;
buf.trim_end().to_string()
} else {
dialoguer::Password::new()
.with_prompt(format!("Enter value for {key}"))
.interact()
.map_err(|e| {
crate::errors::EnvVaultError::CommandFailed(format!("input prompt: {e}"))
})?
};
let keyfile = load_keyfile(cli)?;
let vault_id = path.to_string_lossy();
let password = prompt_password_for_vault(Some(&vault_id))?;
let mut store = VaultStore::open(&path, password.as_bytes(), keyfile.as_deref())?;
let existed = store.get_secret(key).is_ok();
store.set_secret(key, &secret_value)?;
store.save()?;
let op_detail = if existed { "updated" } else { "added" };
crate::audit::log_audit(cli, "set", Some(key), Some(op_detail));
if existed {
output::success(&format!(
"Secret '{}' updated in {}.vault ({} total)",
key,
cli.env,
store.secret_count()
));
} else {
output::success(&format!(
"Secret '{}' added to {}.vault ({} total)",
key,
cli.env,
store.secret_count()
));
}
output::tip("Run your app: envvault run -- <command>");
Ok(())
}