package output import ( "encoding/json" "fmt" "os" "github.com/damirmukimov/city_resource_graph/models" ) // Formatter handles different output formats type Formatter struct { format string // "json", "summary", "table" } // NewFormatter creates a new formatter func NewFormatter(format string) *Formatter { return &Formatter{format: format} } // FormatResult formats the calculation result based on the format type func (f *Formatter) FormatResult(result *models.ModelResult) error { switch f.format { case "json": return f.formatJSON(result) case "summary": return f.formatSummary(result) default: return fmt.Errorf("unsupported format: %s", f.format) } } // formatJSON outputs the result as JSON func (f *Formatter) formatJSON(result *models.ModelResult) error { encoder := json.NewEncoder(os.Stdout) encoder.SetIndent("", " ") return encoder.Encode(result) } // formatSummary outputs a human-readable summary func (f *Formatter) formatSummary(result *models.ModelResult) error { fmt.Println("=== Model Summary ===") fmt.Printf("Years calculated: %d\n", len(result.Years)) fmt.Println() fmt.Println("Summary across all years:") fmt.Printf(" Total Revenue: €%.2f\n", result.Summary.TotalRevenue) fmt.Printf(" Total Costs: €%.2f\n", result.Summary.TotalCosts) fmt.Printf(" Total Profit: €%.2f\n", result.Summary.TotalProfit) fmt.Printf(" Total CO₂ Avoided: %.2f t\n", result.Summary.TotalCO2Avoided) fmt.Printf(" Total Water Reused: %.2f m³\n", result.Summary.TotalWaterReused) fmt.Printf(" Total Waste Diverted: %.2f t\n", result.Summary.TotalWasteDiverted) fmt.Println() fmt.Println("Profitability Analysis:") fmt.Printf(" NPV (10%% discount): €%.2f\n", result.Profitability.NPV) fmt.Printf(" IRR: %.1f%%\n", result.Profitability.IRR) fmt.Printf(" Payback Period: %.1f years\n", result.Profitability.PaybackPeriod) fmt.Println() fmt.Println("Year-by-year breakdown:") for _, year := range result.Years { fmt.Printf("\nYear %d:\n", year.Year) fmt.Printf(" Customers: %d total (%d paying)\n", year.Customer.TotalOrgs, year.Customer.PayingOrgs) fmt.Printf(" Revenue: €%.2f (ARPU: €%.2f)\n", year.Revenue.Total, year.ARPU) fmt.Printf(" Costs: €%.2f\n", year.Costs.Total) fmt.Printf(" Profit: €%.2f (%.1f%% margin)\n", year.Profit, year.Margin) fmt.Printf(" Unit Economics: LTV €%.0f, CAC €%.0f, LTV/CAC %.1f:1\n", year.UnitEconomics.LTV.Blended, year.UnitEconomics.CAC, year.UnitEconomics.LTVToCACRatio) fmt.Printf(" CO₂ Avoided: %.2f t\n", year.Impact.CO2Avoided) if !year.Validation.IsValid() { fmt.Printf(" ⚠️ Validation warnings: %d\n", len(year.Validation.Errors)) for _, err := range year.Validation.Errors { fmt.Printf(" - %s\n", err.Message) } } } return nil } // FormatValidation formats validation results func (f *Formatter) FormatValidation(isValid bool, errors []error) error { if isValid { fmt.Println("✅ Parameters are valid") return nil } fmt.Println("❌ Validation failed:") for _, err := range errors { fmt.Printf(" - %v\n", err) } return nil }