use crate::commands::ssh_helpers::{prompt_for_input, prompt_for_password};
use crate::config::SshConfig;
use crate::logging::{log_error, log_info, log_success};
use anyhow::Result;
use async_ssh2_tokio::client::{AuthMethod, Client, ServerCheckMethod};
use tracing::{error, info};
pub async fn run_redeploy_v2(
password: Option<String>,
username: Option<String>,
host: Option<String>,
project_dir: Option<String>,
debug: bool,
) -> Result<(), String> {
let mut config: SshConfig =
SshConfig::load().map_err(|e| format!("Failed to load SSH config: {}", e))?;
let final_username: Option<String> = username.or_else(|| config.username.clone());
let final_host: Option<String> = host.or_else(|| config.host.clone());
let final_project_dir: Option<String> = project_dir.or_else(|| config.project_dir.clone());
let mut input_password: Option<String> = password;
let resolved_username: String = if let Some(u) = final_username {
u
} else {
let u: String = prompt_for_input("Enter SSH username: ")?;
config.username = Some(u.clone());
u
};
let resolved_host: String = if let Some(h) = final_host {
h
} else {
let h = prompt_for_input("Enter SSH host: ")?;
config.host = Some(h.clone());
h
};
let resolved_project_dir: String = if let Some(d) = final_project_dir {
d
} else {
let d = prompt_for_input("Enter remote project directory: ")?;
config.project_dir = Some(d.clone());
d
};
if input_password.is_none() {
input_password = config.password.clone();
}
let resolved_password: String = if let Some(p) = input_password {
p
} else {
let p = prompt_for_password("Enter SSH password: ")?;
config.password = Some(p.clone());
p
};
config
.save()
.map_err(|e| format!("Failed to save SSH config: {}", e))?;
log_info(
"redeploy_v2",
"Attempting SSH connection",
Some(&format!(
"Host: {}, User: {}",
resolved_host, resolved_username
)),
)
.await?;
let client: Client = Client::connect(
(resolved_host.as_str(), 22),
resolved_username.as_str(),
AuthMethod::with_password(resolved_password.as_str()),
ServerCheckMethod::NoCheck,
)
.await
.map_err(|e| format!("SSH connection failed: {}", e))?;
log_success("redeploy_v2", "SSH connection established", None).await?;
let command_to_execute = format!("cd {} && sudo sh redeploy.sh", resolved_project_dir);
if debug {
log_info(
"redeploy_v2",
"Executing remote command",
Some(&command_to_execute),
)
.await?;
}
let result: async_ssh2_tokio::client::CommandExecutedResult = client
.execute(command_to_execute.as_str())
.await
.map_err(|e| format!("Failed to execute remote command: {}", e))?;
let stdout: String = result.stdout;
let stderr: String = result.stderr;
if !stdout.is_empty() {
log_info("redeploy_v2", "Remote stdout", Some(&stdout)).await?;
info!("Remote Output:\n{}", stdout);
}
if !stderr.is_empty() {
log_error("redeploy_v2", "Remote stderr", Some(&stderr)).await?;
error!("Remote Error:\n{}", stderr);
}
let exit_status: u32 = result.exit_status;
if exit_status == 0 {
log_success(
"redeploy_v2",
"Remote redeploy.sh executed successfully",
None,
)
.await?;
Ok(())
} else {
log_error(
"redeploy_v2",
&format!(
"Remote redeploy.sh failed with exit status: {}",
exit_status
),
None,
)
.await?;
Err(format!(
"Remote redeploy.sh failed with exit status: {}",
exit_status
))
}
}