package firstrechargereward import ( "context" "sort" "strings" "time" "chatapp3-golang/internal/integration" "chatapp3-golang/internal/model" ) func configSnapshotFromModel(row model.FirstRechargeRewardConfig) configSnapshot { return configSnapshot{ ID: row.ID, SysOrigin: strings.ToUpper(strings.TrimSpace(row.SysOrigin)), Enabled: row.Enabled, UpdateTime: row.UpdateTime, } } func levelSnapshotFromModel(row model.FirstRechargeRewardLevel) levelSnapshot { return levelSnapshot{ ID: row.ID, Level: row.Level, RechargeAmountCents: row.RechargeAmountCents, RewardGroupID: row.RewardGroupID, RewardGroupName: strings.TrimSpace(row.RewardGroupName), Enabled: row.Enabled, } } func refConfigSnapshot(value configSnapshot) *configSnapshot { return &value } func buildLevelPayloads( levels []levelSnapshot, rewardItems map[int64][]RewardItem, currentRechargeCents int64, matchedLevel int, admin bool, ) []LevelPayload { payloads := make([]LevelPayload, 0, len(levels)) for _, level := range levels { if !admin && !level.Enabled { continue } payloads = append(payloads, LevelPayload{ ID: level.ID, Level: level.Level, RechargeAmount: formatAmountCents(level.RechargeAmountCents), RechargeAmountCents: level.RechargeAmountCents, RewardGroupID: level.RewardGroupID, RewardGroupName: level.RewardGroupName, RewardItems: rewardItems[level.RewardGroupID], Enabled: level.Enabled, Reached: currentRechargeCents >= level.RechargeAmountCents, Current: matchedLevel > 0 && matchedLevel == level.Level, }) } return payloads } func pickMatchedLevel(levels []levelSnapshot, rechargeAmountCents int64) (levelSnapshot, bool) { var matched levelSnapshot ok := false for _, level := range levels { if !level.Enabled || level.RechargeAmountCents <= 0 || level.RewardGroupID <= 0 { continue } if rechargeAmountCents >= level.RechargeAmountCents && (!ok || level.RechargeAmountCents > matched.RechargeAmountCents) { matched = level ok = true } } return matched, ok } func sortLevels(levels []levelSnapshot) { sort.Slice(levels, func(i, j int) bool { if levels[i].RechargeAmountCents == levels[j].RechargeAmountCents { return levels[i].Level < levels[j].Level } return levels[i].RechargeAmountCents < levels[j].RechargeAmountCents }) } func (s *Service) loadRewardItemsMap(ctx context.Context, levels []levelSnapshot) map[int64][]RewardItem { if s.java == nil { return map[int64][]RewardItem{} } groupIDs := make([]int64, 0) seen := make(map[int64]struct{}) for _, level := range levels { if level.RewardGroupID <= 0 { continue } if _, exists := seen[level.RewardGroupID]; exists { continue } seen[level.RewardGroupID] = struct{}{} groupIDs = append(groupIDs, level.RewardGroupID) } sort.Slice(groupIDs, func(i, j int) bool { return groupIDs[i] < groupIDs[j] }) result := make(map[int64][]RewardItem, len(groupIDs)) for _, groupID := range groupIDs { detail, err := s.java.GetRewardGroupDetail(ctx, groupID) if err != nil { continue } result[groupID] = rewardItemsFromGroup(detail) } return result } func rewardItemsFromGroup(detail integration.RewardGroupDetail) []RewardItem { items := make([]RewardItem, 0, len(detail.RewardConfigList)) for _, item := range detail.RewardConfigList { items = append(items, RewardItem{ ID: int64(item.ID), Type: rewardItemDisplayType(item), Name: strings.TrimSpace(item.Name), Content: strings.TrimSpace(item.Content), Quantity: int64(item.Quantity), Cover: firstNonEmpty(item.Cover, item.SourceURL), Remark: strings.TrimSpace(item.Remark), }) } return items } func rewardItemDisplayType(item integration.RewardGroupItem) string { itemType := strings.ToUpper(strings.TrimSpace(item.Type)) detailType := strings.ToUpper(strings.TrimSpace(item.DetailType)) if itemType == "PROPS" { if detailType != "" && detailType != "PROPS" { return detailType } if isVipRewardItem(item) { return "NOBLE_VIP" } } return itemType } func isVipRewardItem(item integration.RewardGroupItem) bool { name := strings.ToUpper(strings.TrimSpace(item.Name)) remark := strings.ToUpper(strings.TrimSpace(item.Remark)) return strings.Contains(name, "VIP") || strings.Contains(name, "NOBLE") || strings.Contains(remark, "VIP") || strings.Contains(remark, "NOBLE") } func formatDateTime(t time.Time) string { if t.IsZero() { return "" } return t.Format("2006-01-02 15:04:05") } func formatPtrDateTime(t *time.Time) string { if t == nil { return "" } return formatDateTime(*t) }