use std::collections::HashMap;
use serde_json::{json, Value};
use crate::mcp::context::AnalysisContext;
pub fn execute(args: &HashMap<String, Value>, context: &AnalysisContext) -> Result<Value, String> {
let function_name = args
.get("function_name")
.and_then(|v| v.as_str())
.ok_or("Missing required argument 'function_name'")?;
let cfg = context
.cfgs
.get(function_name)
.or_else(|| {
context.cfgs.values().find(|c| {
c.function_name == function_name
|| c.function_name.ends_with(&format!("::{}", function_name))
|| c.function_name.ends_with(&format!(".{}", function_name))
})
})
.ok_or_else(|| {
let available: Vec<&String> = context.cfgs.keys().take(20).collect();
format!(
"No CFG found for function '{}'. Available functions (first 20): {:?}",
function_name, available
)
})?;
let blocks: Vec<Value> = cfg
.blocks()
.map(|(id, block)| {
json!({
"id": id.as_u32(),
"label": block.label,
"is_entry": block.is_entry,
"is_exit": block.is_exit,
"statements_count": block.statements.len(),
})
})
.collect();
let edges: Vec<Value> = cfg
.edges()
.iter()
.map(|edge| {
json!({
"from": edge.from.as_u32(),
"to": edge.to.as_u32(),
"kind": format!("{:?}", edge.kind),
})
})
.collect();
let result = json!({
"function": function_name,
"block_count": blocks.len(),
"edge_count": edges.len(),
"entry": cfg.entry().map(|id| id.as_u32()),
"exit": cfg.exit().map(|id| id.as_u32()),
"blocks": blocks,
"edges": edges,
});
Ok(json!({
"content": [{
"type": "text",
"text": serde_json::to_string_pretty(&result).unwrap_or_default()
}]
}))
}