pmat 3.15.0

PMAT - Zero-config AI context generation and code quality toolkit (CLI, MCP, HTTP)
impl EnhancedReportingService {
    /// Create visualizations
    fn create_visualizations(
        &self,
        results: &AnalysisResults,
        sections: &[ReportSection],
    ) -> Result<Vec<Visualization>> {
        let mut visualizations = Vec::new();

        // Complexity distribution chart
        if let Some(complexity) = &results.complexity_analysis {
            visualizations.push(self.create_complexity_distribution_chart(complexity)?);
        }

        // Health score gauge
        let health_score = self.calculate_health_score(results);
        visualizations.push(self.create_health_score_gauge(health_score)?);

        // Issue distribution pie chart
        visualizations.push(self.create_issue_distribution_chart(sections)?);

        Ok(visualizations)
    }

    /// Create complexity distribution chart
    fn create_complexity_distribution_chart(
        &self,
        complexity: &ComplexityAnalysis,
    ) -> Result<Visualization> {
        let data = serde_json::json!({
            "labels": ["0-5", "6-10", "11-15", "16-20", "20+"],
            "datasets": [{
                "label": "Function Count",
                "data": complexity.distribution,
                "backgroundColor": ["#4CAF50", "#8BC34A", "#FFC107", "#FF9800", "#F44336"]
            }]
        });

        Ok(Visualization {
            title: "Complexity Distribution".to_string(),
            viz_type: VisualizationType::BarChart,
            data,
            config: HashMap::new(),
        })
    }

    /// Create health score gauge
    fn create_health_score_gauge(&self, score: f64) -> Result<Visualization> {
        let data = serde_json::json!({
            "value": score,
            "min": 0,
            "max": 100,
            "thresholds": {
                "critical": 40,
                "high": 60,
                "medium": 80
            }
        });

        Ok(Visualization {
            title: "Overall Health Score".to_string(),
            viz_type: VisualizationType::LineChart, // Would be gauge in real implementation
            data,
            config: HashMap::new(),
        })
    }

    /// Create issue distribution chart
    fn create_issue_distribution_chart(&self, sections: &[ReportSection]) -> Result<Visualization> {
        let mut issue_counts = HashMap::new();

        for section in sections {
            let count = section.findings.len();
            if count > 0 {
                issue_counts.insert(format!("{:?}", section.section_type), count);
            }
        }

        let data = serde_json::json!({
            "labels": issue_counts.keys().collect::<Vec<_>>(),
            "datasets": [{
                "data": issue_counts.values().collect::<Vec<_>>()
            }]
        });

        Ok(Visualization {
            title: "Issue Distribution by Category".to_string(),
            viz_type: VisualizationType::PieChart,
            data,
            config: HashMap::new(),
        })
    }

    /// Format report based on output format
    #[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
    pub async fn format_report(
        &self,
        report: &UnifiedAnalysisReport,
        format: ReportFormat,
    ) -> Result<String> {
        match format {
            ReportFormat::Json => self.format_as_json(report),
            ReportFormat::Markdown => self.format_as_markdown(report),
            ReportFormat::Html => self.format_as_html(report).await,
            ReportFormat::Pdf => self.format_as_pdf(report).await,
            ReportFormat::Dashboard => self.format_as_dashboard(report).await,
        }
    }

    /// Format report as JSON
    fn format_as_json(&self, report: &UnifiedAnalysisReport) -> Result<String> {
        Ok(serde_json::to_string_pretty(report)?)
    }

    /// Format report as Markdown
    fn format_as_markdown(&self, report: &UnifiedAnalysisReport) -> Result<String> {
        let mut md = String::with_capacity(8192);

        // Title
        md.push_str(&format!(
            "# {} Analysis Report\n\n",
            report.metadata.project_name
        ));

        // Metadata
        md.push_str("## Metadata\n\n");
        md.push_str(&format!("- **Date**: {}\n", report.metadata.report_date));
        md.push_str(&format!(
            "- **Tool Version**: {}\n",
            report.metadata.tool_version
        ));
        md.push_str(&format!(
            "- **Files Analyzed**: {}\n",
            report.metadata.analyzed_files
        ));
        md.push_str(&format!(
            "- **Total Lines**: {}\n\n",
            report.metadata.total_lines
        ));

        // Executive Summary
        md.push_str("## Executive Summary\n\n");
        md.push_str(&format!(
            "**Overall Health Score**: {:.1}/100\n\n",
            report.executive_summary.overall_health_score
        ));
        md.push_str(&format!(
            "**Risk Level**: {:?}\n\n",
            report.executive_summary.risk_assessment
        ));

        if !report.executive_summary.key_findings.is_empty() {
            md.push_str("### Key Findings\n\n");
            for finding in &report.executive_summary.key_findings {
                md.push_str(&format!("- {finding}\n"));
            }
            md.push('\n');
        }

        // Sections
        for section in &report.sections {
            md.push_str(&format!("## {}\n\n", section.title));

            // Metrics table
            if !section.metrics.is_empty() {
                md.push_str("| Metric | Value | Threshold | Trend |\n");
                md.push_str("|--------|-------|-----------|-------|\n");

                for (name, metric) in &section.metrics {
                    let threshold = metric
                        .threshold
                        .map_or_else(|| "N/A".to_string(), |t| format!("{t:.1}"));

                    md.push_str(&format!(
                        "| {} | {:.1} {} | {} | {:?} |\n",
                        name, metric.value, metric.unit, threshold, metric.trend
                    ));
                }
                md.push('\n');
            }

            // Findings
            if !section.findings.is_empty() {
                md.push_str("### Findings\n\n");
                for finding in &section.findings {
                    md.push_str(&format!(
                        "- **{:?}**: {}\n",
                        finding.severity, finding.description
                    ));
                }
                md.push('\n');
            }
        }

        // Recommendations
        if !report.recommendations.is_empty() {
            md.push_str("## Recommendations\n\n");

            for rec in &report.recommendations {
                md.push_str(&format!(
                    "### {} - {}\n\n",
                    match rec.priority {
                        Priority::Critical => "🔴 CRITICAL",
                        Priority::High => "🟠 HIGH",
                        Priority::Medium => "🟡 MEDIUM",
                        Priority::Low => "🟢 LOW",
                    },
                    rec.title
                ));
                md.push_str(&format!("{}\n\n", rec.description));
                md.push_str(&format!("**Expected Impact**: {}\n", rec.expected_impact));
                md.push_str(&format!("**Effort**: {:?}\n\n", rec.effort));
            }
        }

        Ok(md)
    }

    /// Format report as HTML
    async fn format_as_html(&self, report: &UnifiedAnalysisReport) -> Result<String> {
        // In a real implementation, this would use templates
        let mut html = String::with_capacity(16384);

        html.push_str("<!DOCTYPE html>\n<html>\n<head>\n");
        html.push_str("<title>Analysis Report</title>\n");
        html.push_str("<style>\n");
        html.push_str("body { font-family: Arial, sans-serif; margin: 40px; }\n");
        html.push_str("h1 { color: #333; }\n");
        html.push_str(".metric { background: #f0f0f0; padding: 10px; margin: 10px 0; }\n");
        html.push_str(".health-score { font-size: 48px; font-weight: bold; }\n");
        html.push_str(".critical { color: #d32f2f; }\n");
        html.push_str(".high { color: #f57c00; }\n");
        html.push_str(".medium { color: #fbc02d; }\n");
        html.push_str(".low { color: #388e3c; }\n");
        html.push_str("</style>\n");
        html.push_str("</head>\n<body>\n");

        html.push_str(&format!(
            "<h1>{} Analysis Report</h1>\n",
            report.metadata.project_name
        ));

        // Executive summary
        html.push_str("<div class='executive-summary'>\n");
        html.push_str("<h2>Executive Summary</h2>\n");
        html.push_str(&format!(
            "<div class='health-score'>{:.1}/100</div>\n",
            report.executive_summary.overall_health_score
        ));
        html.push_str("</div>\n");

        html.push_str("</body>\n</html>");

        Ok(html)
    }

    /// Format report as PDF
    async fn format_as_pdf(&self, _report: &UnifiedAnalysisReport) -> Result<String> {
        // Generate PDF content placeholder
        Ok("[PDF Report Generated]".to_string())
    }

    /// Format report as interactive dashboard
    async fn format_as_dashboard(&self, _report: &UnifiedAnalysisReport) -> Result<String> {
        // Generate dashboard HTML placeholder
        Ok("<html><body><h1>Analysis Dashboard</h1></body></html>".to_string())
    }
}