use crate::storage::database::Database;
use crate::utils::error::gateway_error::{GatewayError, Result};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub struct ReportGenerator {
templates: HashMap<String, ReportTemplate>,
}
#[derive(Debug, Clone)]
pub struct ReportTemplate {
pub name: String,
pub description: String,
pub sections: Vec<ReportSection>,
pub format: ReportFormat,
}
#[derive(Debug, Clone)]
pub struct ReportSection {
pub title: String,
pub section_type: ReportSectionType,
pub queries: Vec<String>,
}
#[derive(Debug, Clone)]
pub enum ReportSectionType {
Summary,
Chart,
Table,
Metrics,
Recommendations,
}
#[derive(Debug, Clone)]
pub enum ReportFormat {
Pdf,
Html,
Json,
Csv,
Excel,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeneratedReport {
pub id: String,
pub title: String,
pub generated_at: DateTime<Utc>,
pub period_start: DateTime<Utc>,
pub period_end: DateTime<Utc>,
pub sections: Vec<ReportSectionData>,
pub summary: ReportSummary,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReportSectionData {
pub title: String,
pub data: serde_json::Value,
pub charts: Vec<ChartData>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChartData {
pub chart_type: String,
pub title: String,
pub data: Vec<DataPoint>,
pub config: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataPoint {
pub x: serde_json::Value,
pub y: serde_json::Value,
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReportSummary {
pub total_requests: u64,
pub total_cost: f64,
pub avg_response_time: f64,
pub success_rate: f64,
pub key_insights: Vec<String>,
pub recommendations: Vec<String>,
}
impl Default for ReportGenerator {
fn default() -> Self {
Self::new()
}
}
impl ReportGenerator {
pub fn new() -> Self {
Self {
templates: Self::default_templates(),
}
}
pub async fn generate(
&self,
template_name: &str,
_user_id: Option<&str>,
start_date: DateTime<Utc>,
end_date: DateTime<Utc>,
_database: &Database,
) -> Result<GeneratedReport> {
let template = self
.templates
.get(template_name)
.ok_or_else(|| GatewayError::NotFound("Report template not found".to_string()))?;
let sections = Vec::new();
Ok(GeneratedReport {
id: uuid::Uuid::new_v4().to_string(),
title: template.name.clone(),
generated_at: Utc::now(),
period_start: start_date,
period_end: end_date,
sections,
summary: ReportSummary {
total_requests: 0,
total_cost: 0.0,
avg_response_time: 0.0,
success_rate: 0.0,
key_insights: Vec::new(),
recommendations: Vec::new(),
},
})
}
pub fn templates(&self) -> &HashMap<String, ReportTemplate> {
&self.templates
}
fn default_templates() -> HashMap<String, ReportTemplate> {
let mut templates = HashMap::new();
templates.insert(
"usage_summary".to_string(),
ReportTemplate {
name: "Usage Summary Report".to_string(),
description: "Comprehensive usage and cost summary".to_string(),
sections: vec![
ReportSection {
title: "Executive Summary".to_string(),
section_type: ReportSectionType::Summary,
queries: vec!["summary_stats".to_string()],
},
ReportSection {
title: "Cost Analysis".to_string(),
section_type: ReportSectionType::Chart,
queries: vec!["cost_trends".to_string()],
},
],
format: ReportFormat::Pdf,
},
);
templates
}
}
#[cfg(test)]
#[path = "reports_tests.rs"]
mod tests;