use crate::config::SshConfig;
use crate::logging::{log_error, log_info, log_success};
use anyhow::Result;
use std::io::{self, Write};
use async_ssh2_tokio::client::{Client, AuthMethod, ServerCheckMethod};
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::load().map_err(|e| format!("Failed to load SSH config: {}", e))?;
let final_username = username.or_else(|| config.username.clone());
let final_host = host.or_else(|| config.host.clone());
let final_project_dir = project_dir.or_else(|| config.project_dir.clone());
let mut input_password = password;
let resolved_username = if let Some(u) = final_username {
u
} else {
let u = prompt_for_input("Enter SSH username: ")?;
config.username = Some(u.clone());
u
};
let resolved_host = 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 = 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 = 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::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 = client.execute(command_to_execute.as_str()).await.map_err(|e| format!("Failed to execute remote command: {}", e))?;
let stdout = result.stdout;
let stderr = result.stderr;
if !stdout.is_empty() {
log_info("redeploy_v2", "Remote stdout", Some(&stdout)).await?;
println!("\x1b[92mRemote Output:\x1b[0m\n{}", stdout);
}
if !stderr.is_empty() {
log_error("redeploy_v2", "Remote stderr", Some(&stderr)).await?;
eprintln!("\x1b[91mRemote Error:\x1b[0m\n{}", stderr);
}
let exit_status = 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))
}
}
fn prompt_for_input(prompt: &str) -> Result<String, String> {
print!("\x1b[96m{}\x1b[0m", prompt);
io::stdout().flush().map_err(|e| format!("Failed to flush stdout: {}", e))?;
let mut input = String::new();
io::stdin().read_line(&mut input).map_err(|e| format!("Failed to read input: {}", e))?;
Ok(input.trim().to_string())
}
fn prompt_for_password(prompt: &str) -> Result<String, String> {
rpassword::prompt_password(prompt)
.map_err(|e| format!("Failed to read password: {}", e))
}