package exporter import ( "encoding/csv" "encoding/json" "fmt" "os" "strings" "time" "bargain-scraper/internal/models" ) type Exporter struct{} func New() *Exporter { return &Exporter{} } func (e *Exporter) ExportToJSON(products []models.StorageProduct, filename string) error { if filename == "" { filename = fmt.Sprintf("storage_products_%s.json", time.Now().Format("2006-01-02_150405")) } data, err := json.MarshalIndent(products, "", " ") if err != nil { return fmt.Errorf("failed to marshal JSON: %w", err) } err = os.WriteFile(filename, data, 0644) if err != nil { return fmt.Errorf("failed to write JSON file: %w", err) } return nil } func (e *Exporter) ExportToCSV(products []models.StorageProduct, filename string) error { if filename == "" { filename = fmt.Sprintf("storage_products_%s.csv", time.Now().Format("2006-01-02_150405")) } file, err := os.Create(filename) if err != nil { return fmt.Errorf("failed to create CSV file: %w", err) } defer file.Close() writer := csv.NewWriter(file) defer writer.Flush() headers := []string{"ID", "Name", "Price", "Capacity", "Interface", "FormFactor", "Brand", "PartNumber", "StockStatus", "URL", "ScrapedAt"} if err := writer.Write(headers); err != nil { return fmt.Errorf("failed to write CSV headers: %w", err) } for _, p := range products { row := []string{ p.ID, p.Name, p.Price, p.Capacity, p.Interface, p.FormFactor, p.Brand, p.PartNumber, p.StockStatus, p.URL, p.ScrapedAt.Format(time.RFC3339), } if err := writer.Write(row); err != nil { return fmt.Errorf("failed to write CSV row: %w", err) } } return nil } func (e *Exporter) PrintToConsole(products []models.StorageProduct) string { var b strings.Builder b.WriteString("\n") b.WriteString("═══════════════════════════════════════════════════════════════════════════════\n") b.WriteString(fmt.Sprintf(" STORAGE PRODUCTS (%d items) \n", len(products))) b.WriteString("═══════════════════════════════════════════════════════════════════════════════\n") b.WriteString("\n") headerFmt := " %-4s | %-40s | %-10s | %-8s | %-6s | %-10s | %-12s\n" separator := "──────┼──────────────────────────────────────────┬────────────┬──────────┼────────┼────────────┼──────────────\n" b.WriteString(fmt.Sprintf(headerFmt, "#", "Name", "Capacity", "Interface", "Factor", "Stock", "Price")) b.WriteString(separator) for i, p := range products { name := p.Name if len(name) > 40 { name = name[:37] + "..." } capacity := p.Capacity if capacity == "" { capacity = "-" } interface_ := p.Interface if interface_ == "" { interface_ = "-" } formFactor := p.FormFactor if formFactor == "" { formFactor = "-" } stock := p.StockStatus if stock == "" { stock = "-" } price := p.Price if price == "" { price = "-" } b.WriteString(fmt.Sprintf(headerFmt, fmt.Sprintf("%d", i+1), name, capacity, interface_, formFactor, stock, price, )) } b.WriteString("\n") b.WriteString(fmt.Sprintf("Total: %d products\n", len(products))) return b.String() } func (e *Exporter) Export(products []models.StorageProduct, format string, filename string) error { switch strings.ToLower(format) { case "json": return e.ExportToJSON(products, filename) case "csv": return e.ExportToCSV(products, filename) default: return fmt.Errorf("unsupported format: %s (use 'json' or 'csv')", format) } }