package repository import ( "context" "encoding/json" "fmt" "os" "strconv" "time" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/jackc/pgx/v5/pgtype" ) func (s *Store) SaveNonLiveMarket(ctx context.Context, m domain.Market) error { if len(m.Odds) == 0 { fmt.Printf("⚠️ Market has no odds: %s (%s)\n", m.MarketType, m.EventID) return nil } for _, raw := range m.Odds { var item map[string]interface{} if err := json.Unmarshal(raw, &item); err != nil { fmt.Printf("❌ Invalid odd JSON for %s (%s): %v\n", m.MarketType, m.EventID, err) continue } header := getString(item["header"]) name := getString(item["name"]) handicap := getString(item["handicap"]) oddsVal := getFloat(item["odds"]) // Marshal the full list of odds for reference (if needed) rawOddsBytes, _ := json.Marshal(m.Odds) params := dbgen.InsertNonLiveOddParams{ EventID: pgtype.Text{String: m.EventID, Valid: m.EventID != ""}, Fi: pgtype.Text{String: m.FI, Valid: m.FI != ""}, RawEventID: pgtype.Text{String: m.EventID, Valid: m.EventID != ""}, MarketType: m.MarketType, MarketName: pgtype.Text{String: m.MarketName, Valid: m.MarketName != ""}, MarketCategory: pgtype.Text{String: m.MarketCategory, Valid: m.MarketCategory != ""}, MarketID: pgtype.Text{String: m.MarketID, Valid: m.MarketID != ""}, Header: pgtype.Text{String: header, Valid: header != ""}, Name: pgtype.Text{String: name, Valid: name != ""}, Handicap: pgtype.Text{String: handicap, Valid: handicap != ""}, OddsValue: pgtype.Float8{Float64: oddsVal, Valid: oddsVal != 0}, Section: m.MarketCategory, Category: pgtype.Text{Valid: false}, RawOdds: rawOddsBytes, } err := s.queries.InsertNonLiveOdd(ctx, params) if err != nil { fmt.Printf("❌ Failed to insert odd for market %s (%s): %v\n", m.MarketType, m.EventID, err) _ = writeFailedMarketLog(m, err) continue } fmt.Printf("✅ Inserted odd: %s | type=%s | header=%s | name=%s\n", m.EventID, m.MarketType, header, name) } return nil } func writeFailedMarketLog(m domain.Market, err error) error { logDir := "logs" logFile := logDir + "/failed_markets.log" if mkErr := os.MkdirAll(logDir, 0755); mkErr != nil { return mkErr } f, fileErr := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if fileErr != nil { return fileErr } defer f.Close() entry := struct { Time string `json:"time"` Error string `json:"error"` Record domain.Market `json:"record"` }{ Time: time.Now().Format(time.RFC3339), Error: err.Error(), Record: m, } jsonData, _ := json.MarshalIndent(entry, "", " ") _, writeErr := f.WriteString(string(jsonData) + "\n\n") return writeErr } func getString(v interface{}) string { if s, ok := v.(string); ok { return s } return "" } func getFloat(v interface{}) float64 { if s, ok := v.(string); ok { f, err := strconv.ParseFloat(s, 64) if err == nil { return f } } return 0 } func (s *Store) GetUpcomingEventIDs(ctx context.Context) ([]string, error) { return s.queries.GetUpcomingEventIDs(ctx) }