use serde_json::json;
use std::sync::Arc;
use turbovault_core::prelude::*;
use turbovault_vault::VaultManager;
pub struct AnalysisTools {
pub manager: Arc<VaultManager>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct VaultStats {
pub total_files: usize,
pub total_links: usize,
pub orphaned_files: usize,
pub average_links_per_file: f64,
}
impl AnalysisTools {
pub fn new(manager: Arc<VaultManager>) -> Self {
Self { manager }
}
pub async fn get_vault_stats(&self) -> Result<VaultStats> {
let stats = self.manager.get_stats().await?;
Ok(VaultStats {
total_files: stats.total_files,
total_links: stats.total_links,
orphaned_files: stats.orphaned_files,
average_links_per_file: stats.average_links_per_file,
})
}
pub async fn list_orphaned_notes(&self) -> Result<Vec<String>> {
let orphans = self.manager.get_orphaned_notes().await?;
Ok(orphans
.into_iter()
.filter_map(|p| p.to_str().map(|s| s.to_string()))
.collect())
}
pub async fn detect_cycles(&self) -> Result<Vec<Vec<String>>> {
let graph = self.manager.link_graph();
let graph_read = graph.read().await;
let cycles = graph_read
.cycles()
.into_iter()
.map(|cycle| {
cycle
.into_iter()
.filter_map(|p| p.to_str().map(|s| s.to_string()))
.collect()
})
.collect();
Ok(cycles)
}
pub async fn get_link_density(&self) -> Result<f64> {
let stats = self.manager.get_stats().await?;
if stats.total_files <= 1 {
return Ok(0.0);
}
let possible_links = (stats.total_files as f64) * ((stats.total_files as f64) - 1.0);
let density = (stats.total_links as f64) / possible_links;
Ok(density)
}
pub async fn get_connectivity_metrics(&self) -> Result<serde_json::Value> {
let stats = self.manager.get_stats().await?;
let density = self.get_link_density().await?;
Ok(json!({
"total_files": stats.total_files,
"total_links": stats.total_links,
"orphaned_files": stats.orphaned_files,
"connected_files": stats.total_files - stats.orphaned_files,
"average_links_per_file": stats.average_links_per_file,
"link_density": density,
"connectivity_rate": if stats.total_files > 0 {
(stats.total_files - stats.orphaned_files) as f64 / stats.total_files as f64
} else {
0.0
}
}))
}
}