use anyhow::{Result, Context};
use colored::Colorize;
use tabled::{Table, Tabled, settings::Style};
use serde::{Serialize, Deserialize};
use crate::config::Config;
use crate::commands::GatewayCommands;
use crate::utils::{print_success, print_error, print_info};
#[derive(Tabled, Serialize, Deserialize)]
struct RouteRow {
#[tabled(rename = "ID")]
id: String,
#[tabled(rename = "Path")]
path: String,
#[tabled(rename = "Service")]
service: String,
#[tabled(rename = "Methods")]
methods: String,
#[tabled(rename = "Status")]
status: String,
}
#[derive(Tabled, Serialize, Deserialize)]
struct StatsRow {
#[tabled(rename = "Service")]
service: String,
#[tabled(rename = "Requests")]
requests: u64,
#[tabled(rename = "Success Rate")]
success_rate: String,
#[tabled(rename = "Avg Latency")]
avg_latency: String,
#[tabled(rename = "P99 Latency")]
p99_latency: String,
}
pub async fn handle_command(command: GatewayCommands, config: &Config) -> Result<()> {
match command {
GatewayCommands::Routes { service } => {
list_routes(service, config).await?
}
GatewayCommands::AddRoute { path, service, methods } => {
add_route(&path, &service, methods, config).await?
}
GatewayCommands::RemoveRoute { id } => {
remove_route(&id, config).await?
}
GatewayCommands::Stats { service } => {
show_stats(service, config).await?
}
GatewayCommands::Test { config: config_file } => {
test_configuration(config_file, config).await?
}
}
Ok(())
}
async fn list_routes(service_filter: Option<String>, config: &Config) -> Result<()> {
let routes = vec![
RouteRow {
id: "route-1".to_string(),
path: "/api/users/*".to_string(),
service: "user-service".to_string(),
methods: "GET, POST, PUT".to_string(),
status: "active".green().to_string(),
},
RouteRow {
id: "route-2".to_string(),
path: "/api/orders/*".to_string(),
service: "order-service".to_string(),
methods: "ALL".to_string(),
status: "active".green().to_string(),
},
];
let filtered_routes: Vec<_> = if let Some(filter) = service_filter {
routes.into_iter()
.filter(|r| r.service.contains(&filter))
.collect()
} else {
routes
};
if filtered_routes.is_empty() {
print_info("No routes found");
} else {
let table = Table::new(&filtered_routes)
.with(Style::modern())
.to_string();
println!("{}", table);
}
Ok(())
}
async fn add_route(
path: &str,
service: &str,
methods: Vec<String>,
config: &Config,
) -> Result<()> {
let methods_str = if methods.is_empty() {
"ALL"
} else {
&methods.join(", ")
};
print_success(&format!(
"Route added successfully:\n Path: {}\n Service: {}\n Methods: {}",
path, service, methods_str
));
Ok(())
}
async fn remove_route(id: &str, config: &Config) -> Result<()> {
print_success(&format!("Route '{}' removed successfully", id));
Ok(())
}
async fn show_stats(service_filter: Option<String>, config: &Config) -> Result<()> {
let stats = vec![
StatsRow {
service: "user-service".to_string(),
requests: 125432,
success_rate: "99.8%".green().to_string(),
avg_latency: "23ms".to_string(),
p99_latency: "145ms".to_string(),
},
StatsRow {
service: "order-service".to_string(),
requests: 87654,
success_rate: "99.2%".green().to_string(),
avg_latency: "45ms".to_string(),
p99_latency: "234ms".to_string(),
},
];
let filtered_stats: Vec<_> = if let Some(filter) = service_filter {
stats.into_iter()
.filter(|s| s.service.contains(&filter))
.collect()
} else {
stats
};
if filtered_stats.is_empty() {
print_info("No statistics found");
} else {
println!("{}", "Gateway Statistics".bold());
println!("{}", "=".repeat(50));
let table = Table::new(&filtered_stats)
.with(Style::modern())
.to_string();
println!("{}", table);
println!("\n{}: {}",
"Period".bold(),
"Last 24 hours".to_string()
);
}
Ok(())
}
async fn test_configuration(
config_file: Option<String>,
config: &Config,
) -> Result<()> {
print_info("Testing gateway configuration...");
let config_path = config_file.unwrap_or_else(|| "gateway.yaml".to_string());
println!("\n{}", "Configuration Test Results".bold());
println!("{}", "=".repeat(50));
let checks = vec![
("Syntax validation", true, ""),
("Service connectivity", true, ""),
("Health check endpoints", true, ""),
("Rate limit configuration", true, ""),
("Circuit breaker settings", true, ""),
];
let mut all_passed = true;
for (check, passed, error) in checks {
if passed {
println!("{} {}", "✓".green(), check);
} else {
println!("{} {} - {}", "✗".red(), check, error.red());
all_passed = false;
}
}
println!();
if all_passed {
print_success("All configuration checks passed!");
} else {
print_error("Some configuration checks failed");
return Err(anyhow::anyhow!("Configuration validation failed"));
}
Ok(())
}