package processor import ( "context" "fmt" "time" "apskel-pos-be/internal/models" "apskel-pos-be/internal/repository" "github.com/google/uuid" ) type CustomerPointsProcessor struct { customerPointsRepo repository.CustomerPointsRepository gameRepo *repository.GameRepository } func NewCustomerPointsProcessor(customerPointsRepo repository.CustomerPointsRepository, gameRepo *repository.GameRepository) *CustomerPointsProcessor { return &CustomerPointsProcessor{ customerPointsRepo: customerPointsRepo, gameRepo: gameRepo, } } // Existing gamification methods - placeholder implementations func (p *CustomerPointsProcessor) CreateCustomerPoints(ctx context.Context, req *models.CreateCustomerPointsRequest) (*models.CustomerPointsResponse, error) { // TODO: Implement this method return nil, fmt.Errorf("not implemented") } func (p *CustomerPointsProcessor) GetCustomerPoints(ctx context.Context, id uuid.UUID) (*models.CustomerPointsResponse, error) { // TODO: Implement this method return nil, fmt.Errorf("not implemented") } func (p *CustomerPointsProcessor) GetCustomerPointsByCustomerID(ctx context.Context, customerID uuid.UUID) (*models.CustomerPointsResponse, error) { // TODO: Implement this method return nil, fmt.Errorf("not implemented") } func (p *CustomerPointsProcessor) ListCustomerPoints(ctx context.Context, query *models.ListCustomerPointsQuery) (*models.PaginatedCustomerPointsResponse, error) { // Return empty paginated response for now return &models.PaginatedCustomerPointsResponse{ Data: []models.CustomerPointsResponse{}, TotalCount: 0, Page: 1, Limit: 10, TotalPages: 0, }, nil } func (p *CustomerPointsProcessor) UpdateCustomerPoints(ctx context.Context, id uuid.UUID, req *models.UpdateCustomerPointsRequest) (*models.CustomerPointsResponse, error) { // TODO: Implement this method return nil, fmt.Errorf("not implemented") } func (p *CustomerPointsProcessor) DeleteCustomerPoints(ctx context.Context, id uuid.UUID) error { // TODO: Implement this method return fmt.Errorf("not implemented") } func (p *CustomerPointsProcessor) AddPoints(ctx context.Context, customerID uuid.UUID, points int64) (*models.CustomerPointsResponse, error) { // TODO: Implement this method return nil, fmt.Errorf("not implemented") } func (p *CustomerPointsProcessor) DeductPoints(ctx context.Context, customerID uuid.UUID, points int64) (*models.CustomerPointsResponse, error) { // TODO: Implement this method return nil, fmt.Errorf("not implemented") } func (p *CustomerPointsProcessor) GetCustomerTotalPointsAPI(ctx context.Context, customerID string) (*models.GetCustomerPointsResponse, error) { // Get total points totalPoints, err := p.customerPointsRepo.GetCustomerTotalPoints(ctx, customerID) if err != nil { return nil, fmt.Errorf("failed to get customer total points: %w", err) } // Get points history (last 10 records) pointsHistory, err := p.customerPointsRepo.GetCustomerPointsHistory(ctx, customerID, 10) if err != nil { return nil, fmt.Errorf("failed to get customer points history: %w", err) } // Convert to response format var historyItems []models.PointsHistoryItem for _, point := range pointsHistory { historyItems = append(historyItems, models.PointsHistoryItem{ ID: point.ID.String(), Points: point.Balance, Type: "BALANCE", Description: "Points balance", CreatedAt: point.CreatedAt, }) } var lastUpdated time.Time if len(pointsHistory) > 0 { lastUpdated = pointsHistory[0].CreatedAt } return &models.GetCustomerPointsResponse{ Status: "SUCCESS", Message: "Customer points retrieved successfully.", Data: &models.GetCustomerPointsResponseData{ TotalPoints: totalPoints, PointsHistory: historyItems, LastUpdated: lastUpdated, }, }, nil } func (p *CustomerPointsProcessor) GetCustomerTotalTokensAPI(ctx context.Context, customerID string) (*models.GetCustomerTokensResponse, error) { // Get total tokens totalTokens, err := p.customerPointsRepo.GetCustomerTotalTokens(ctx, customerID) if err != nil { return nil, fmt.Errorf("failed to get customer total tokens: %w", err) } // Get tokens history (last 10 records) tokensHistory, err := p.customerPointsRepo.GetCustomerTokensHistory(ctx, customerID, 10) if err != nil { return nil, fmt.Errorf("failed to get customer tokens history: %w", err) } // Convert to response format var historyItems []models.TokensHistoryItem for _, token := range tokensHistory { historyItems = append(historyItems, models.TokensHistoryItem{ ID: token.ID.String(), Tokens: token.Balance, Type: string(token.TokenType), Description: "Tokens balance", CreatedAt: token.CreatedAt, }) } var lastUpdated time.Time if len(tokensHistory) > 0 { lastUpdated = tokensHistory[0].CreatedAt } return &models.GetCustomerTokensResponse{ Status: "SUCCESS", Message: "Customer tokens retrieved successfully.", Data: &models.GetCustomerTokensResponseData{ TotalTokens: totalTokens, TokensHistory: historyItems, LastUpdated: lastUpdated, }, }, nil } func (p *CustomerPointsProcessor) GetCustomerWalletAPI(ctx context.Context, customerID string) (*models.GetCustomerWalletResponse, error) { // Get total points totalPoints, err := p.customerPointsRepo.GetCustomerTotalPoints(ctx, customerID) if err != nil { return nil, fmt.Errorf("failed to get customer total points: %w", err) } // Get total tokens totalTokens, err := p.customerPointsRepo.GetCustomerTotalTokens(ctx, customerID) if err != nil { return nil, fmt.Errorf("failed to get customer total tokens: %w", err) } // Get points history (last 5 records) pointsHistory, err := p.customerPointsRepo.GetCustomerPointsHistory(ctx, customerID, 5) if err != nil { return nil, fmt.Errorf("failed to get customer points history: %w", err) } // Get tokens history (last 5 records) tokensHistory, err := p.customerPointsRepo.GetCustomerTokensHistory(ctx, customerID, 5) if err != nil { return nil, fmt.Errorf("failed to get customer tokens history: %w", err) } // Convert to response format var pointsHistoryItems []models.PointsHistoryItem var tokensHistoryItems []models.TokensHistoryItem var lastUpdated time.Time for _, point := range pointsHistory { pointsHistoryItems = append(pointsHistoryItems, models.PointsHistoryItem{ ID: point.ID.String(), Points: point.Balance, Type: "BALANCE", Description: "Points balance", CreatedAt: point.CreatedAt, }) if point.CreatedAt.After(lastUpdated) { lastUpdated = point.CreatedAt } } for _, token := range tokensHistory { tokensHistoryItems = append(tokensHistoryItems, models.TokensHistoryItem{ ID: token.ID.String(), Tokens: token.Balance, Type: string(token.TokenType), Description: "Tokens balance", CreatedAt: token.CreatedAt, }) if token.CreatedAt.After(lastUpdated) { lastUpdated = token.CreatedAt } } return &models.GetCustomerWalletResponse{ Status: "SUCCESS", Message: "Customer wallet retrieved successfully.", Data: &models.GetCustomerWalletResponseData{ TotalPoints: totalPoints, TotalTokens: totalTokens, PointsHistory: pointsHistoryItems, TokensHistory: tokensHistoryItems, LastUpdated: lastUpdated, }, }, nil } // GetCustomerGamesAPI gets active SPIN games for customers func (p *CustomerPointsProcessor) GetCustomerGamesAPI(ctx context.Context) (*models.GetCustomerGamesResponse, error) { // Get active SPIN games games, err := p.gameRepo.GetActiveSpinGames(ctx) if err != nil { return nil, fmt.Errorf("failed to get active SPIN games: %w", err) } // Convert to response format var gameResponses []models.CustomerGameResponse for _, game := range games { var prizeResponses []models.CustomerGamePrizeResponse for _, prize := range game.Prizes { prizeResponses = append(prizeResponses, models.CustomerGamePrizeResponse{ ID: prize.ID, GameID: prize.GameID, Name: prize.Name, Image: prize.Image, Metadata: (*map[string]interface{})(&prize.Metadata), CreatedAt: prize.CreatedAt, UpdatedAt: prize.UpdatedAt, }) } gameResponses = append(gameResponses, models.CustomerGameResponse{ ID: game.ID, Name: game.Name, Type: string(game.Type), IsActive: game.IsActive, Metadata: (*map[string]interface{})(&game.Metadata), Prizes: prizeResponses, CreatedAt: game.CreatedAt, UpdatedAt: game.UpdatedAt, }) } return &models.GetCustomerGamesResponse{ Status: "SUCCESS", Message: "Customer games retrieved successfully.", Data: &models.GetCustomerGamesResponseData{ Games: gameResponses, }, }, nil } // GetFerrisWheelGameAPI gets the Ferris Wheel game for customers func (p *CustomerPointsProcessor) GetFerrisWheelGameAPI(ctx context.Context) (*models.GetFerrisWheelGameResponse, error) { // Get Ferris Wheel game game, err := p.gameRepo.GetFerrisWheelGame(ctx) if err != nil { return nil, fmt.Errorf("failed to get Ferris Wheel game: %w", err) } // Convert prizes to response format var prizeResponses []models.CustomerGamePrizeResponse for _, prize := range game.Prizes { prizeResponses = append(prizeResponses, models.CustomerGamePrizeResponse{ ID: prize.ID, GameID: prize.GameID, Name: prize.Name, Image: prize.Image, Metadata: (*map[string]interface{})(&prize.Metadata), CreatedAt: prize.CreatedAt, UpdatedAt: prize.UpdatedAt, }) } // Convert game to response format gameResponse := models.CustomerGameResponse{ ID: game.ID, Name: game.Name, Type: string(game.Type), IsActive: game.IsActive, Metadata: (*map[string]interface{})(&game.Metadata), Prizes: prizeResponses, CreatedAt: game.CreatedAt, UpdatedAt: game.UpdatedAt, } return &models.GetFerrisWheelGameResponse{ Status: "SUCCESS", Message: "Ferris Wheel game retrieved successfully.", Data: &models.GetFerrisWheelGameResponseData{ Game: gameResponse, Prizes: prizeResponses, }, }, nil }