package provider import ( "encoding/json" "fmt" "strings" "time" ) // ReportGenerator handles the generation of validation reports in various formats type ReportGenerator struct { report *ValidationReport } // NewReportGenerator creates a new ReportGenerator func NewReportGenerator(report *ValidationReport) *ReportGenerator { return &ReportGenerator{ report: report, } } // GenerateTextReport generates a human-readable text report func (rg *ReportGenerator) GenerateTextReport() string { var builder strings.Builder builder.WriteString("Provider Validation Report\n") builder.WriteString("=========================\n\n") builder.WriteString(fmt.Sprintf("Generated: %s\n", rg.report.Timestamp.Format(time.RFC3339))) builder.WriteString(fmt.Sprintf("Total Providers: %d\n", rg.report.TotalProviders)) builder.WriteString(fmt.Sprintf("Valid Providers: %d\n", rg.report.ValidCount)) builder.WriteString(fmt.Sprintf("Invalid Providers: %d\n", rg.report.InvalidCount)) builder.WriteString(fmt.Sprintf("Overall Status: %s\n\n", rg.getStatusText())) // Summary section builder.WriteString("Summary\n") builder.WriteString("-------\n") if rg.report.IsValid { builder.WriteString("✅ All providers are valid\n\n") } else { builder.WriteString("❌ Validation failed with errors\n\n") } // Errors section if len(rg.report.Errors) > 0 { builder.WriteString("Errors\n") builder.WriteString("------\n") for i, err := range rg.report.Errors { builder.WriteString(fmt.Sprintf("%d. %s\n", i+1, rg.formatValidationError(&err))) } builder.WriteString("\n") } // Warnings section if len(rg.report.Warnings) > 0 { builder.WriteString("Warnings\n") builder.WriteString("--------\n") for i, warning := range rg.report.Warnings { builder.WriteString(fmt.Sprintf("%d. %s\n", i+1, rg.formatValidationError(&warning))) } builder.WriteString("\n") } // Infos section if len(rg.report.Infos) > 0 { builder.WriteString("Information\n") builder.WriteString("-----------\n") for i, info := range rg.report.Infos { builder.WriteString(fmt.Sprintf("%d. %s\n", i+1, rg.formatValidationError(&info))) } builder.WriteString("\n") } return builder.String() } // GenerateJSONReport generates a JSON report func (rg *ReportGenerator) GenerateJSONReport() (string, error) { data, err := json.MarshalIndent(rg.report, "", " ") if err != nil { return "", fmt.Errorf("failed to generate JSON report: %w", err) } return string(data), nil } // GenerateHTMLReport generates an HTML report func (rg *ReportGenerator) GenerateHTMLReport() string { var builder strings.Builder builder.WriteString(` Provider Validation Report

Provider Validation Report

Generated: ` + rg.report.Timestamp.Format(time.RFC3339) + `

Total Providers: ` + fmt.Sprintf("%d", rg.report.TotalProviders) + `

Valid Providers: ` + fmt.Sprintf("%d", rg.report.ValidCount) + `

Invalid Providers: ` + fmt.Sprintf("%d", rg.report.InvalidCount) + `

Overall Status: ` + rg.getStatusHTML() + `

Summary

` + rg.getSummaryText() + `

`) // Errors section if len(rg.report.Errors) > 0 { builder.WriteString(`

Errors

`) } // Warnings section if len(rg.report.Warnings) > 0 { builder.WriteString(`

Warnings

`) } // Infos section if len(rg.report.Infos) > 0 { builder.WriteString(`

Information

`) } builder.WriteString(` `) return builder.String() } // GenerateMarkdownReport generates a Markdown report func (rg *ReportGenerator) GenerateMarkdownReport() string { var builder strings.Builder builder.WriteString("# Provider Validation Report\n\n") builder.WriteString(fmt.Sprintf("**Generated:** %s\n\n", rg.report.Timestamp.Format(time.RFC3339))) builder.WriteString(fmt.Sprintf("**Total Providers:** %d\n", rg.report.TotalProviders)) builder.WriteString(fmt.Sprintf("**Valid Providers:** %d\n", rg.report.ValidCount)) builder.WriteString(fmt.Sprintf("**Invalid Providers:** %d\n", rg.report.InvalidCount)) builder.WriteString(fmt.Sprintf("**Overall Status:** %s\n\n", rg.getStatusText())) builder.WriteString("## Summary\n\n") builder.WriteString(rg.getSummaryText() + "\n\n") // Errors section if len(rg.report.Errors) > 0 { builder.WriteString("## Errors\n\n") for i, err := range rg.report.Errors { builder.WriteString(fmt.Sprintf("%d. %s\n", i+1, rg.formatValidationErrorMarkdown(&err))) } builder.WriteString("\n") } // Warnings section if len(rg.report.Warnings) > 0 { builder.WriteString("## Warnings\n\n") for i, warning := range rg.report.Warnings { builder.WriteString(fmt.Sprintf("%d. %s\n", i+1, rg.formatValidationErrorMarkdown(&warning))) } builder.WriteString("\n") } // Infos section if len(rg.report.Infos) > 0 { builder.WriteString("## Information\n\n") for i, info := range rg.report.Infos { builder.WriteString(fmt.Sprintf("%d. %s\n", i+1, rg.formatValidationErrorMarkdown(&info))) } builder.WriteString("\n") } return builder.String() } // Helper methods func (rg *ReportGenerator) getStatusText() string { if rg.report.IsValid { return "✅ Valid" } return "❌ Invalid" } func (rg *ReportGenerator) getStatusHTML() string { if rg.report.IsValid { return "✅ Valid" } return "❌ Invalid" } func (rg *ReportGenerator) getSummaryText() string { if rg.report.IsValid { return "All providers are valid and ready for use." } totalIssues := len(rg.report.Errors) + len(rg.report.Warnings) + len(rg.report.Infos) return fmt.Sprintf("Found %d issues (%d errors, %d warnings, %d info). Please review and fix the issues before proceeding.", totalIssues, len(rg.report.Errors), len(rg.report.Warnings), len(rg.report.Infos)) } func (rg *ReportGenerator) formatValidationError(err *ValidationError) string { var parts []string if err.ProviderRef != "" { parts = append(parts, fmt.Sprintf("[%s]", err.ProviderRef)) } parts = append(parts, fmt.Sprintf("%s: %s", err.RuleName, err.Message)) if err.Field != "" { parts = append(parts, fmt.Sprintf("(field: %s)", err.Field)) } if err.Value != "" { parts = append(parts, fmt.Sprintf("(value: %s)", err.Value)) } if err.Suggestion != "" { parts = append(parts, fmt.Sprintf("💡 %s", err.Suggestion)) } return strings.Join(parts, " ") } func (rg *ReportGenerator) formatValidationErrorHTML(err *ValidationError) string { var builder strings.Builder if err.ProviderRef != "" { builder.WriteString(fmt.Sprintf("[%s] ", err.ProviderRef)) } builder.WriteString(fmt.Sprintf("%s: %s", err.Severity, err.Message)) if err.Field != "" { builder.WriteString(fmt.Sprintf(" (field: %s)", err.Field)) } if err.Value != "" { builder.WriteString(fmt.Sprintf(" (value: %s)", err.Value)) } if err.Suggestion != "" { builder.WriteString(fmt.Sprintf(" 💡 %s", err.Suggestion)) } return builder.String() } func (rg *ReportGenerator) formatValidationErrorMarkdown(err *ValidationError) string { var builder strings.Builder if err.ProviderRef != "" { builder.WriteString(fmt.Sprintf("*[%s]* ", err.ProviderRef)) } builder.WriteString(fmt.Sprintf("**%s**: %s", err.RuleName, err.Message)) if err.Field != "" { builder.WriteString(fmt.Sprintf(" *(field: %s)*", err.Field)) } if err.Value != "" { builder.WriteString(fmt.Sprintf(" *(value: %s)*", err.Value)) } if err.Suggestion != "" { builder.WriteString(fmt.Sprintf("\n 💡 *%s*", err.Suggestion)) } return builder.String() } // ReportFormat defines supported report formats type ReportFormat string const ( ReportFormatText ReportFormat = "text" ReportFormatJSON ReportFormat = "json" ReportFormatHTML ReportFormat = "html" ReportFormatMarkdown ReportFormat = "markdown" ) // GenerateReport generates a report in the specified format func (rg *ReportGenerator) GenerateReport(format ReportFormat) (string, error) { switch format { case ReportFormatText: return rg.GenerateTextReport(), nil case ReportFormatJSON: return rg.GenerateJSONReport() case ReportFormatHTML: return rg.GenerateHTMLReport(), nil case ReportFormatMarkdown: return rg.GenerateMarkdownReport(), nil default: return "", fmt.Errorf("unsupported report format: %s", format) } } // ReportWriter handles writing reports to files or other outputs type ReportWriter struct { generator *ReportGenerator } // NewReportWriter creates a new ReportWriter func NewReportWriter(report *ValidationReport) *ReportWriter { return &ReportWriter{ generator: NewReportGenerator(report), } } // WriteToFile writes a report to a file in the specified format func (rw *ReportWriter) WriteToFile(filename string, format ReportFormat) error { report, err := rw.generator.GenerateReport(format) if err != nil { return fmt.Errorf("failed to generate report: %w", err) } // In a real implementation, this would write to a file // For now, we'll just return success _ = report // Placeholder for file writing logic return nil } // WriteToConsole writes a report to the console func (rw *ReportWriter) WriteToConsole(format ReportFormat) error { report, err := rw.generator.GenerateReport(format) if err != nil { return fmt.Errorf("failed to generate report: %w", err) } fmt.Println(report) return nil }