package sync import ( "fmt" "regexp" "gorm.io/gorm" "rhemawavetech.com/rhemawave/internal/db" "rhemawavetech.com/rhemawave/internal/logger" "rhemawavetech.com/rhemawave/internal/netreq" ) var htmlRegex = regexp.MustCompile(`<[^>]*>`) // SyncProclamations fetches data from the API, cleans it, and updates the local DB. // It returns the slice of proclamations so the UI can update immediately. func SyncProclamations(apiURL string, database *gorm.DB) ([]db.Proclamation, error) { fullURL := fmt.Sprintf("%s/proclamations", apiURL) // 1. Fetch from API proclamations, err := netreq.GetJSON[db.Proclamation](fullURL) if err != nil { // If we're offline or API is down, we log it but don't crash. // The UI can still use whatever is currently in the DB. logger.Error("Proclamation sync failed, skipping update: %v", err) return nil, err } // 2. Data Transformation (Cleaning) for i := range proclamations { proclamations[i].Content = htmlRegex.ReplaceAllString(proclamations[i].Content, "") } // 3. Persist to Database // Using Transaction ensures we don't end up with partial data if something fails err = database.Transaction(func(tx *gorm.DB) error { if err := tx.Omit("selected").Save(&proclamations).Error; err != nil { return err } return nil }) if err != nil { logger.Error("Failed to save synced proclamations: %v", err) return nil, err } logger.Info("Successfully synced proclamations: %d", len(proclamations)) return proclamations, nil } func SyncCategories(apiURL string, database *gorm.DB) ([]db.ProclamationCategory, error) { fullURL := fmt.Sprintf("%s/categories", apiURL) categories, err := netreq.GetJSON[db.ProclamationCategory](fullURL) if err != nil { logger.Error("Category sync failed, skipping update: %v", err) return nil, err } err = database.Transaction(func(tx *gorm.DB) error { if err := tx.Save(&categories).Error; err != nil { return err } return nil }) logger.Info("Successfully synced proclamation categories: %d", len(categories)) return categories, nil }