use anyhow::{Context, Result};
use matchy::{Database, QueryResult};
use serde_json::json;
use std::path::Path;
use crate::cli_utils::{data_value_to_json, format_cidr};
pub fn cmd_query(database: &Path, query: &str, quiet: bool) -> Result<()> {
let db = Database::from(database.to_str().unwrap())
.open()
.with_context(|| format!("Failed to load database: {}", database.display()))?;
let result = db
.lookup(query)
.with_context(|| format!("Query failed for: {query}"))?;
let found = matches!(result, Some(QueryResult::Pattern { ref pattern_ids, .. }) if !pattern_ids.is_empty())
|| matches!(result, Some(QueryResult::Ip { .. }));
if quiet {
std::process::exit(if found { 0 } else { 1 });
}
match result {
Some(QueryResult::Pattern {
pattern_ids, data, ..
}) => {
if pattern_ids.is_empty() {
println!("[]");
} else {
let mut results = Vec::new();
for (i, &_pattern_id) in pattern_ids.iter().enumerate() {
if let Some(Some(ref d)) = data.get(i) {
results.push(data_value_to_json(d));
}
}
println!("{}", serde_json::to_string_pretty(&json!(results))?);
}
}
Some(QueryResult::Ip {
data, prefix_len, ..
}) => {
let cidr = format_cidr(query, prefix_len);
let mut result = data_value_to_json(&data);
if let serde_json::Value::Object(ref mut map) = result {
map.insert("cidr".to_string(), json!(cidr));
map.insert("prefix_len".to_string(), json!(prefix_len));
}
println!("{}", serde_json::to_string_pretty(&json!([result]))?);
}
Some(QueryResult::NotFound) | None => {
println!("[]");
}
}
std::process::exit(if found { 0 } else { 1 });
}