1#![allow(dead_code)]
6
7use crate::environmental_monitor::types::*;
8use anyhow::Result;
9use std::collections::HashMap;
10use std::time::{Duration, SystemTime};
11use tracing::info;
12
13#[derive(Debug)]
15pub struct EnvironmentalReportingEngine {
16 report_templates: HashMap<String, ReportTemplate>,
17 automated_reports: Vec<AutomatedReport>,
18 dashboard_metrics: EnvironmentalDashboardMetrics,
19}
20
21#[derive(Debug, Clone)]
22struct ReportTemplate {
23 template_name: String,
24 sections: Vec<ReportSection>,
25 target_audience: String,
26 frequency: ReportFrequency,
27}
28
29#[derive(Debug, Clone)]
30struct ReportSection {
31 section_name: String,
32 metrics_included: Vec<String>,
33 visualization_type: VisualizationType,
34}
35#[derive(Debug, Clone)]
36pub struct AutomatedReport {
37 report_id: String,
38 generated_at: SystemTime,
39 report_type: String,
40 content: String,
41}
42
43const MAX_AUTOMATED_REPORTS: usize = 100;
48
49impl EnvironmentalReportingEngine {
50 pub fn new() -> Self {
52 Self {
53 report_templates: Self::initialize_report_templates(),
54 automated_reports: Vec::new(),
55 dashboard_metrics: EnvironmentalDashboardMetrics {
56 total_energy_consumed_kwh: 0.0,
57 total_co2_emissions_kg: 0.0,
58 current_power_usage_watts: 0.0,
59 energy_efficiency_score: 0.0,
60 carbon_intensity_gco2_kwh: 0.0,
61 cost_per_hour_usd: 0.0,
62 trend: TrendDirection::Stable,
63 },
64 }
65 }
66
67 pub async fn generate_environmental_report(
75 &mut self,
76 report_type: ReportType,
77 ) -> Result<EnvironmentalReport> {
78 info!("Generating environmental impact report: {:?}", report_type);
79
80 let report = match report_type {
81 ReportType::Summary => self.generate_summary_report().await?,
82 ReportType::Detailed => self.generate_detailed_report().await?,
83 ReportType::Technical => self.generate_technical_report().await?,
84 ReportType::Executive => self.generate_executive_report().await?,
85 ReportType::Compliance => self.generate_compliance_report().await?,
86 };
87
88 self.store_automated_report(&report)?;
89
90 Ok(report)
91 }
92
93 pub async fn generate_daily_report(&self) -> Result<EnvironmentalReport> {
95 let period_start = SystemTime::now() - Duration::from_secs(24 * 3600);
96 let period_end = SystemTime::now();
97
98 Ok(EnvironmentalReport {
99 report_id: format!("daily-{}", chrono::Utc::now().format("%Y%m%d")),
100 report_type: ReportType::Summary,
101 generated_at: SystemTime::now(),
102 period_start,
103 period_end,
104 summary: "Daily environmental impact summary showing energy consumption, carbon emissions, and efficiency metrics".to_string(),
105 metrics: EnvironmentalDashboardMetrics {
106 total_energy_consumed_kwh: 120.5,
107 total_co2_emissions_kg: 48.2,
108 current_power_usage_watts: 750.0,
109 energy_efficiency_score: 0.87,
110 carbon_intensity_gco2_kwh: 400.0,
111 cost_per_hour_usd: 14.46,
112 trend: TrendDirection::Decreasing,
113 },
114 detailed_analysis: "Energy consumption remained within optimal ranges. Peak power usage occurred during training hours (10 AM - 4 PM). Carbon intensity was 12% lower than regional average due to increased renewable energy generation.".to_string(),
115 recommendations: vec![
116 SustainabilityRecommendation {
117 category: RecommendationCategory::Energy,
118 priority: RecommendationPriority::Medium,
119 title: "Schedule training during low-carbon hours".to_string(),
120 description: "Schedule intensive workloads during hours 2-6 AM when carbon intensity is lowest".to_string(),
121 potential_impact: "15% carbon reduction possible".to_string(),
122 implementation_steps: vec![
123 "Analyze workload scheduling patterns".to_string(),
124 "Implement automated scheduling system".to_string(),
125 "Monitor carbon impact improvements".to_string(),
126 ],
127 },
128 SustainabilityRecommendation {
129 category: RecommendationCategory::Performance,
130 priority: RecommendationPriority::Low,
131 title: "Optimize cooling efficiency".to_string(),
132 description: "Implement dynamic cooling adjustments based on workload intensity".to_string(),
133 potential_impact: "8% energy reduction in cooling systems".to_string(),
134 implementation_steps: vec![
135 "Install smart temperature controls".to_string(),
136 "Monitor cooling system efficiency".to_string(),
137 "Adjust cooling based on real-time needs".to_string(),
138 ],
139 },
140 ],
141 charts: vec![
142 ChartData {
143 chart_type: VisualizationType::LineChart,
144 title: "Daily Energy Consumption".to_string(),
145 data_points: vec![
146 ("00:00".to_string(), 45.2),
147 ("06:00".to_string(), 52.1),
148 ("12:00".to_string(), 78.9),
149 ("18:00".to_string(), 65.3),
150 ],
151 labels: vec!["Time".to_string(), "kWh".to_string()],
152 },
153 ChartData {
154 chart_type: VisualizationType::BarChart,
155 title: "Carbon Emissions by Activity".to_string(),
156 data_points: vec![
157 ("Training".to_string(), 32.1),
158 ("Inference".to_string(), 12.8),
159 ("Data Processing".to_string(), 3.3),
160 ],
161 labels: vec!["Activity".to_string(), "kg CO2".to_string()],
162 },
163 ],
164 })
165 }
166
167 pub async fn generate_weekly_report(&self) -> Result<EnvironmentalReport> {
169 let period_start = SystemTime::now() - Duration::from_secs(7 * 24 * 3600);
170 let period_end = SystemTime::now();
171
172 Ok(EnvironmentalReport {
173 report_id: format!("weekly-{}", chrono::Utc::now().format("%Y-W%W")),
174 report_type: ReportType::Summary,
175 generated_at: SystemTime::now(),
176 period_start,
177 period_end,
178 summary: "Weekly environmental impact analysis showing trends and optimization opportunities".to_string(),
179 metrics: EnvironmentalDashboardMetrics {
180 total_energy_consumed_kwh: 843.5,
181 total_co2_emissions_kg: 337.4,
182 current_power_usage_watts: 750.0,
183 energy_efficiency_score: 0.85,
184 carbon_intensity_gco2_kwh: 400.0,
185 cost_per_hour_usd: 101.22,
186 trend: TrendDirection::Decreasing,
187 },
188 detailed_analysis: "Week-over-week improvements: 12% reduction in carbon emissions, 5% improvement in energy efficiency. Training workloads showed 18% better utilization due to batch size optimization.".to_string(),
189 recommendations: vec![
190 SustainabilityRecommendation {
191 category: RecommendationCategory::Sustainability,
192 priority: RecommendationPriority::High,
193 title: "Implement weekly optimization schedule".to_string(),
194 description: "Create recurring optimization cycles to maintain improvement momentum".to_string(),
195 potential_impact: "Sustained 10-15% efficiency improvements".to_string(),
196 implementation_steps: vec![
197 "Schedule weekly efficiency audits".to_string(),
198 "Automate optimization recommendations".to_string(),
199 "Track improvement metrics consistently".to_string(),
200 ],
201 },
202 ],
203 charts: vec![
204 ChartData {
205 chart_type: VisualizationType::LineChart,
206 title: "Weekly Energy Efficiency Trend".to_string(),
207 data_points: vec![
208 ("Week 1".to_string(), 0.80),
209 ("Week 2".to_string(), 0.82),
210 ("Week 3".to_string(), 0.85),
211 ("Week 4".to_string(), 0.85),
212 ],
213 labels: vec!["Week".to_string(), "Efficiency Score".to_string()],
214 },
215 ],
216 })
217 }
218
219 pub async fn generate_monthly_report(&self) -> Result<EnvironmentalReport> {
221 let period_start = SystemTime::now() - Duration::from_secs(30 * 24 * 3600);
222 let period_end = SystemTime::now();
223
224 Ok(EnvironmentalReport {
225 report_id: format!("monthly-{}", chrono::Utc::now().format("%Y-%m")),
226 report_type: ReportType::Detailed,
227 generated_at: SystemTime::now(),
228 period_start,
229 period_end,
230 summary: "Monthly comprehensive analysis of environmental impact, goal progress, and strategic recommendations".to_string(),
231 metrics: EnvironmentalDashboardMetrics {
232 total_energy_consumed_kwh: 3674.2,
233 total_co2_emissions_kg: 1469.7,
234 current_power_usage_watts: 750.0,
235 energy_efficiency_score: 0.83,
236 carbon_intensity_gco2_kwh: 400.0,
237 cost_per_hour_usd: 440.90,
238 trend: TrendDirection::Decreasing,
239 },
240 detailed_analysis: "Monthly highlights: Achieved 65% progress on carbon reduction goal. Cost savings of $127 from optimization initiatives. Implemented 3 of 5 planned efficiency improvements. Regional carbon intensity averaged 15% below baseline.".to_string(),
241 recommendations: vec![
242 SustainabilityRecommendation {
243 category: RecommendationCategory::Performance,
244 priority: RecommendationPriority::High,
245 title: "Focus on model efficiency optimization".to_string(),
246 description: "Prioritize architectural improvements for next month's optimization cycle".to_string(),
247 potential_impact: "20-30% efficiency improvement potential".to_string(),
248 implementation_steps: vec![
249 "Audit current model architectures".to_string(),
250 "Implement pruning and quantization".to_string(),
251 "Measure performance impact".to_string(),
252 "Scale successful optimizations".to_string(),
253 ],
254 },
255 SustainabilityRecommendation {
256 category: RecommendationCategory::Sustainability,
257 priority: RecommendationPriority::Medium,
258 title: "Consider renewable energy procurement".to_string(),
259 description: "Investigate renewable energy contracts for next quarter".to_string(),
260 potential_impact: "40-60% carbon footprint reduction".to_string(),
261 implementation_steps: vec![
262 "Research renewable energy providers".to_string(),
263 "Analyze cost-benefit of renewable contracts".to_string(),
264 "Negotiate renewable energy agreements".to_string(),
265 "Plan transition timeline".to_string(),
266 ],
267 },
268 ],
269 charts: vec![
270 ChartData {
271 chart_type: VisualizationType::LineChart,
272 title: "Monthly Carbon Emissions Trend".to_string(),
273 data_points: vec![
274 ("Week 1".to_string(), 415.2),
275 ("Week 2".to_string(), 380.1),
276 ("Week 3".to_string(), 342.7),
277 ("Week 4".to_string(), 331.7),
278 ],
279 labels: vec!["Week".to_string(), "kg CO2".to_string()],
280 },
281 ChartData {
282 chart_type: VisualizationType::PieChart,
283 title: "Energy Usage by Activity Type".to_string(),
284 data_points: vec![
285 ("Training".to_string(), 2574.0),
286 ("Inference".to_string(), 735.0),
287 ("Data Processing".to_string(), 220.0),
288 ("Development".to_string(), 145.2),
289 ],
290 labels: vec!["Activity".to_string(), "kWh".to_string()],
291 },
292 ],
293 })
294 }
295
296 pub async fn generate_annual_report(&self) -> Result<EnvironmentalReport> {
298 let period_start = SystemTime::now() - Duration::from_secs(365 * 24 * 3600);
299 let period_end = SystemTime::now();
300
301 Ok(EnvironmentalReport {
302 report_id: format!("annual-{}", chrono::Utc::now().format("%Y")),
303 report_type: ReportType::Executive,
304 generated_at: SystemTime::now(),
305 period_start,
306 period_end,
307 summary: "Annual environmental impact summary with strategic insights and long-term sustainability planning".to_string(),
308 metrics: EnvironmentalDashboardMetrics {
309 total_energy_consumed_kwh: 45000.0,
310 total_co2_emissions_kg: 18000.0,
311 current_power_usage_watts: 750.0,
312 energy_efficiency_score: 0.81,
313 carbon_intensity_gco2_kwh: 400.0,
314 cost_per_hour_usd: 5400.0,
315 trend: TrendDirection::Decreasing,
316 },
317 detailed_analysis: "Annual achievements: 18 tonnes CO2 total footprint (equivalent to 41,580 car miles). Implemented sustainability program with 35% efficiency improvement over baseline. Achieved ISO 14001 preliminary compliance. Established carbon offset program covering 60% of emissions.".to_string(),
318 recommendations: vec![
319 SustainabilityRecommendation {
320 category: RecommendationCategory::Sustainability,
321 priority: RecommendationPriority::Critical,
322 title: "Implement comprehensive carbon reduction strategy".to_string(),
323 description: "Develop multi-year carbon neutrality roadmap with specific milestones".to_string(),
324 potential_impact: "Path to carbon neutrality by 2027".to_string(),
325 implementation_steps: vec![
326 "Set science-based carbon reduction targets".to_string(),
327 "Invest in renewable energy infrastructure".to_string(),
328 "Implement advanced carbon accounting".to_string(),
329 "Establish carbon offset verification program".to_string(),
330 ],
331 },
332 SustainabilityRecommendation {
333 category: RecommendationCategory::Performance,
334 priority: RecommendationPriority::High,
335 title: "Invest in next-generation efficient hardware".to_string(),
336 description: "Plan hardware refresh cycle with focus on energy-efficient compute".to_string(),
337 potential_impact: "30-40% efficiency improvement over current hardware".to_string(),
338 implementation_steps: vec![
339 "Evaluate next-generation GPU efficiency".to_string(),
340 "Plan phased hardware upgrade strategy".to_string(),
341 "Implement hardware efficiency monitoring".to_string(),
342 "Track ROI of efficiency investments".to_string(),
343 ],
344 },
345 ],
346 charts: vec![
347 ChartData {
348 chart_type: VisualizationType::LineChart,
349 title: "Annual Carbon Footprint Progress".to_string(),
350 data_points: vec![
351 ("Q1".to_string(), 5200.0),
352 ("Q2".to_string(), 4800.0),
353 ("Q3".to_string(), 4200.0),
354 ("Q4".to_string(), 3800.0),
355 ],
356 labels: vec!["Quarter".to_string(), "kg CO2".to_string()],
357 },
358 ChartData {
359 chart_type: VisualizationType::Gauge,
360 title: "Sustainability Goals Progress".to_string(),
361 data_points: vec![
362 ("Carbon Reduction".to_string(), 72.0),
363 ("Energy Efficiency".to_string(), 65.0),
364 ("Renewable Energy".to_string(), 45.0),
365 ("Waste Reduction".to_string(), 58.0),
366 ],
367 labels: vec!["Goal".to_string(), "Progress %".to_string()],
368 },
369 ],
370 })
371 }
372
373 async fn generate_summary_report(&self) -> Result<EnvironmentalReport> {
375 self.generate_daily_report().await
376 }
377
378 async fn generate_detailed_report(&self) -> Result<EnvironmentalReport> {
379 self.generate_monthly_report().await
380 }
381
382 async fn generate_technical_report(&self) -> Result<EnvironmentalReport> {
383 let mut report = self.generate_monthly_report().await?;
384 report.report_type = ReportType::Technical;
385
386 report.detailed_analysis = format!(
388 "{}\n\nTechnical Details:\n\
389 - Average GPU utilization: 84.2%\n\
390 - Memory bandwidth efficiency: 76.8%\n\
391 - Compute intensity: 12.4 FLOPS/Watt\n\
392 - Cooling system PUE: 1.18\n\
393 - Network energy overhead: 3.2%\n\
394 - Storage system efficiency: 89.1%",
395 report.detailed_analysis
396 );
397
398 report.charts.push(ChartData {
400 chart_type: VisualizationType::Heatmap,
401 title: "Hardware Utilization Matrix".to_string(),
402 data_points: vec![
403 ("GPU-0".to_string(), 85.2),
404 ("GPU-1".to_string(), 82.7),
405 ("CPU-0".to_string(), 45.3),
406 ("Memory".to_string(), 67.8),
407 ],
408 labels: vec!["Component".to_string(), "Utilization %".to_string()],
409 });
410
411 Ok(report)
412 }
413
414 async fn generate_executive_report(&self) -> Result<EnvironmentalReport> {
415 let mut report = self.generate_monthly_report().await?;
416 report.report_type = ReportType::Executive;
417
418 report.summary = "Executive Summary: Monthly environmental performance shows strong progress toward sustainability goals with measurable business benefits including cost reduction and operational efficiency gains.".to_string();
420
421 report.detailed_analysis = "Key Business Impacts:\n\
422 • $127 monthly cost savings from efficiency optimization\n\
423 • 15% reduction in operational energy costs\n\
424 • Improved compliance posture for environmental regulations\n\
425 • Enhanced corporate sustainability credentials\n\
426 • Risk mitigation for carbon pricing exposure\n\n\
427 Strategic Recommendations:\n\
428 • Accelerate renewable energy procurement timeline\n\
429 • Invest in efficiency monitoring infrastructure\n\
430 • Establish formal sustainability governance structure"
431 .to_string();
432
433 Ok(report)
434 }
435
436 async fn generate_compliance_report(&self) -> Result<EnvironmentalReport> {
437 let mut report = self.generate_monthly_report().await?;
438 report.report_type = ReportType::Compliance;
439
440 report.summary = "Environmental Compliance Report: Assessment of current compliance status against environmental regulations and certification requirements.".to_string();
442
443 report.detailed_analysis = "Compliance Status:\n\
444 • ISO 14001: 65% compliance (target: 100%)\n\
445 • Energy Star: 45% compliance (target: 80%)\n\
446 • Carbon Trust Standard: 30% compliance (target: 90%)\n\
447 • Regional emissions reporting: Fully compliant\n\
448 • Energy efficiency disclosure: Fully compliant\n\n\
449 Required Actions:\n\
450 • Implement formal environmental management system\n\
451 • Establish third-party verification processes\n\
452 • Develop comprehensive carbon accounting system\n\
453 • Create audit trail for all environmental metrics"
454 .to_string();
455
456 report.recommendations.push(SustainabilityRecommendation {
458 category: RecommendationCategory::Sustainability,
459 priority: RecommendationPriority::Critical,
460 title: "Accelerate compliance program implementation".to_string(),
461 description: "Fast-track environmental management system implementation to meet regulatory requirements".to_string(),
462 potential_impact: "Full regulatory compliance within 6 months".to_string(),
463 implementation_steps: vec![
464 "Engage environmental compliance consultant".to_string(),
465 "Implement formal environmental management system".to_string(),
466 "Establish third-party verification processes".to_string(),
467 "Schedule compliance audits".to_string(),
468 ],
469 });
470
471 Ok(report)
472 }
473
474 fn store_automated_report(&mut self, report: &EnvironmentalReport) -> Result<()> {
477 let automated_report = AutomatedReport {
478 report_id: report.report_id.clone(),
479 generated_at: report.generated_at,
480 report_type: format!("{:?}", report.report_type),
481 content: format!("{}\n\n{}", report.summary, report.detailed_analysis),
482 };
483
484 let report_id = automated_report.report_id.clone();
485 self.automated_reports.push(automated_report);
486 if self.automated_reports.len() > MAX_AUTOMATED_REPORTS {
487 self.automated_reports.remove(0);
488 }
489 info!("Stored automated report: {}", report_id);
490 Ok(())
491 }
492
493 pub fn update_dashboard_metrics(&mut self, metrics: EnvironmentalDashboardMetrics) {
495 self.dashboard_metrics = metrics;
496 }
497
498 pub fn get_dashboard_metrics(&self) -> &EnvironmentalDashboardMetrics {
500 &self.dashboard_metrics
501 }
502
503 pub fn get_automated_reports(&self) -> &[AutomatedReport] {
505 &self.automated_reports
506 }
507
508 fn initialize_report_templates() -> HashMap<String, ReportTemplate> {
510 let mut templates = HashMap::new();
511
512 templates.insert(
513 "daily_summary".to_string(),
514 ReportTemplate {
515 template_name: "Daily Environmental Summary".to_string(),
516 target_audience: "Operations Team".to_string(),
517 frequency: ReportFrequency::Daily,
518 sections: vec![
519 ReportSection {
520 section_name: "Energy Consumption".to_string(),
521 metrics_included: vec![
522 "total_energy_kwh".to_string(),
523 "peak_power".to_string(),
524 ],
525 visualization_type: VisualizationType::LineChart,
526 },
527 ReportSection {
528 section_name: "Carbon Emissions".to_string(),
529 metrics_included: vec![
530 "total_co2_kg".to_string(),
531 "carbon_intensity".to_string(),
532 ],
533 visualization_type: VisualizationType::BarChart,
534 },
535 ],
536 },
537 );
538
539 templates.insert(
540 "executive_monthly".to_string(),
541 ReportTemplate {
542 template_name: "Executive Monthly Report".to_string(),
543 target_audience: "Executive Leadership".to_string(),
544 frequency: ReportFrequency::Monthly,
545 sections: vec![
546 ReportSection {
547 section_name: "Strategic Metrics".to_string(),
548 metrics_included: vec![
549 "sustainability_score".to_string(),
550 "cost_savings".to_string(),
551 ],
552 visualization_type: VisualizationType::Gauge,
553 },
554 ReportSection {
555 section_name: "Goal Progress".to_string(),
556 metrics_included: vec![
557 "carbon_goal_progress".to_string(),
558 "efficiency_goal_progress".to_string(),
559 ],
560 visualization_type: VisualizationType::Table,
561 },
562 ],
563 },
564 );
565
566 templates
567 }
568
569 pub async fn generate_custom_report(&self, period: Duration) -> Result<EnvironmentalReport> {
571 let period_start = SystemTime::now() - period;
572 let period_end = SystemTime::now();
573
574 Ok(EnvironmentalReport {
575 report_id: format!("custom-{}", chrono::Utc::now().format("%Y%m%d-%H%M")),
576 report_type: ReportType::Summary,
577 generated_at: SystemTime::now(),
578 period_start,
579 period_end,
580 summary: format!("Custom period environmental analysis covering {:.1} days",
581 period.as_secs_f64() / (24.0 * 3600.0)),
582 metrics: self.dashboard_metrics.clone(),
583 detailed_analysis: "Custom period analysis showing environmental metrics and trends for the specified timeframe".to_string(),
584 recommendations: vec![
585 SustainabilityRecommendation {
586 category: RecommendationCategory::Performance,
587 priority: RecommendationPriority::Medium,
588 title: "Continue monitoring trends".to_string(),
589 description: "Maintain current monitoring practices and look for optimization opportunities".to_string(),
590 potential_impact: "Ongoing efficiency improvements".to_string(),
591 implementation_steps: vec![
592 "Review custom period insights".to_string(),
593 "Identify actionable optimization opportunities".to_string(),
594 "Plan implementation of improvements".to_string(),
595 ],
596 },
597 ],
598 charts: vec![
599 ChartData {
600 chart_type: VisualizationType::LineChart,
601 title: "Custom Period Energy Trend".to_string(),
602 data_points: vec![
603 ("Start".to_string(), 100.0),
604 ("Mid".to_string(), 95.5),
605 ("End".to_string(), 88.2),
606 ],
607 labels: vec!["Time".to_string(), "Energy".to_string()],
608 },
609 ],
610 })
611 }
612}
613
614#[cfg(test)]
615mod tests {
616 use super::*;
617
618 #[tokio::test]
619 async fn generated_reports_are_really_retained() {
620 let mut engine = EnvironmentalReportingEngine::new();
621 assert!(engine.get_automated_reports().is_empty());
622
623 let report = engine
624 .generate_environmental_report(ReportType::Summary)
625 .await
626 .expect("report generation");
627
628 let stored = engine.get_automated_reports();
632 assert_eq!(
633 stored.len(),
634 1,
635 "the generated report must really be retained"
636 );
637 assert_eq!(stored[0].report_id, report.report_id);
638 assert!(stored[0].content.contains(&report.summary));
639 }
640
641 #[tokio::test]
642 async fn the_automated_report_log_is_bounded() {
643 let mut engine = EnvironmentalReportingEngine::new();
644 for _ in 0..(MAX_AUTOMATED_REPORTS + 5) {
645 engine
646 .generate_environmental_report(ReportType::Summary)
647 .await
648 .expect("report generation");
649 }
650 assert_eq!(
651 engine.get_automated_reports().len(),
652 MAX_AUTOMATED_REPORTS,
653 "the oldest reports must be dropped, not accumulated without bound"
654 );
655 }
656
657 #[test]
658 fn test_reporting_engine_creation() {
659 let engine = EnvironmentalReportingEngine::new();
660 assert!(!engine.report_templates.is_empty());
661 }
662
663 #[tokio::test]
664 async fn test_daily_report_generation() {
665 let engine = EnvironmentalReportingEngine::new();
666 let report = engine.generate_daily_report().await.expect("async operation failed");
667
668 assert!(!report.report_id.is_empty());
669 assert!(!report.summary.is_empty());
670 assert!(!report.recommendations.is_empty());
671 assert!(!report.charts.is_empty());
672 }
673
674 #[tokio::test]
675 async fn test_all_report_types() {
676 let mut engine = EnvironmentalReportingEngine::new();
677
678 let summary_report = engine
679 .generate_environmental_report(ReportType::Summary)
680 .await
681 .expect("async operation failed");
682 let detailed_report = engine
683 .generate_environmental_report(ReportType::Detailed)
684 .await
685 .expect("async operation failed");
686 let technical_report = engine
687 .generate_environmental_report(ReportType::Technical)
688 .await
689 .expect("async operation failed");
690 let executive_report = engine
691 .generate_environmental_report(ReportType::Executive)
692 .await
693 .expect("async operation failed");
694 let compliance_report = engine
695 .generate_environmental_report(ReportType::Compliance)
696 .await
697 .expect("async operation failed");
698
699 assert_eq!(summary_report.report_type, ReportType::Summary);
700 assert_eq!(detailed_report.report_type, ReportType::Detailed);
701 assert_eq!(technical_report.report_type, ReportType::Technical);
702 assert_eq!(executive_report.report_type, ReportType::Executive);
703 assert_eq!(compliance_report.report_type, ReportType::Compliance);
704 }
705
706 #[tokio::test]
707 async fn test_custom_report_generation() {
708 let engine = EnvironmentalReportingEngine::new();
709 let custom_period = Duration::from_secs(7 * 24 * 3600); let report = engine
712 .generate_custom_report(custom_period)
713 .await
714 .expect("async operation failed");
715
716 assert!(report.summary.contains("7.0 days"));
717 assert!(!report.charts.is_empty());
718 }
719
720 #[test]
721 fn test_dashboard_metrics_update() {
722 let mut engine = EnvironmentalReportingEngine::new();
723
724 let new_metrics = EnvironmentalDashboardMetrics {
725 total_energy_consumed_kwh: 250.0,
726 total_co2_emissions_kg: 100.0,
727 current_power_usage_watts: 800.0,
728 energy_efficiency_score: 0.9,
729 carbon_intensity_gco2_kwh: 350.0,
730 cost_per_hour_usd: 15.0,
731 trend: TrendDirection::Decreasing,
732 };
733
734 engine.update_dashboard_metrics(new_metrics.clone());
735
736 let updated_metrics = engine.get_dashboard_metrics();
737 assert_eq!(updated_metrics.total_energy_consumed_kwh, 250.0);
738 assert_eq!(updated_metrics.energy_efficiency_score, 0.9);
739 }
740
741 #[tokio::test]
742 async fn test_report_content_quality() {
743 let engine = EnvironmentalReportingEngine::new();
744 let report = engine.generate_monthly_report().await.expect("async operation failed");
745
746 assert!(report.summary.len() > 50);
748 assert!(report.detailed_analysis.len() > 100);
749 assert!(!report.recommendations.is_empty());
750
751 for rec in &report.recommendations {
753 assert!(!rec.title.is_empty());
754 assert!(!rec.description.is_empty());
755 assert!(!rec.implementation_steps.is_empty());
756 }
757
758 for chart in &report.charts {
760 assert!(!chart.title.is_empty());
761 assert!(!chart.data_points.is_empty());
762 assert!(!chart.labels.is_empty());
763 }
764 }
765}