use crate::{fs, network};
use anyhow::Result;
use clap::Parser;
use colored::Colorize;
use dialoguer::{Select, theme::ColorfulTheme};
#[derive(Parser, Debug)]
pub struct LsRemote {
pub version_prefix: Option<String>,
}
impl LsRemote {
pub async fn call(self) -> Result<()> {
let mut versions = network::get_available_versions().await?;
if let Some(prefix) = &self.version_prefix {
versions.retain(|v| v.starts_with(prefix) || v == prefix);
}
if versions.is_empty() {
println!("{} No remote versions found.", "💡".yellow());
return Ok(());
}
let installed = fs::list_installed_versions().unwrap_or_default();
let mut display_items = Vec::new();
let mut target_versions = Vec::new();
let mut minors = std::collections::BTreeMap::new();
let mut highest_overall = None;
for v in &versions {
highest_overall = Some(v.clone());
let parts: Vec<&str> = v.split('.').collect();
if parts.len() >= 2 {
let minor = format!("{}.{}", parts[0], parts[1]);
minors.insert(minor, v.clone()); }
}
if let Some(highest) = highest_overall {
display_items.push(format!("latest ({})", highest).bold().to_string());
target_versions.push(highest);
}
for (minor, highest_patch) in minors.iter().rev() {
display_items.push(
format!("{} ({})", minor, highest_patch)
.bold()
.cyan()
.to_string(),
);
target_versions.push(highest_patch.clone());
}
display_items.push("---".dimmed().to_string());
target_versions.push("".to_string());
for v in versions.iter().rev() {
if installed.contains(v) {
display_items.push(format!("{} {} {}", "✓".green(), v, "(installed)".dimmed()));
} else {
display_items.push(format!(" {}", v));
}
target_versions.push(v.clone());
}
let selection = Select::with_theme(&ColorfulTheme::default())
.with_prompt("Select a PHP version to install")
.default(0)
.items(&display_items)
.interact_opt()?;
let selected = match selection {
Some(idx) => {
let target = &target_versions[idx];
if target.is_empty() {
println!("{} Invalid selection.", "✗".red());
return Ok(());
}
target
}
None => {
println!("{} Operation cancelled.", "✗".red());
return Ok(());
}
};
if !installed.contains(selected) {
crate::commands::install::execute_install(selected).await?;
} else {
println!(
"{} PHP {} is already installed.",
"✓".green(),
selected.bold()
);
}
Ok(())
}
}