package processor import ( "context" "fmt" "apskel-pos-be/internal/models" "apskel-pos-be/internal/repository" "github.com/google/uuid" ) type CustomerPointsProcessor struct { walletQuery *WalletQueryProcessor gameRepo *repository.GameRepository } func NewCustomerPointsProcessor(walletQuery *WalletQueryProcessor, gameRepo *repository.GameRepository) *CustomerPointsProcessor { return &CustomerPointsProcessor{ walletQuery: walletQuery, 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") } // The three endpoints below are the customer app's balance screens. They read the // EnakPoint & EnakCoin wallet; customer_points and customer_tokens are no longer used // for balances (docs/prd-point-coin.md ยง9). func (p *CustomerPointsProcessor) GetCustomerTotalPointsAPI(ctx context.Context, customerID string) (*models.GetCustomerPointsResponse, error) { id, err := parseWalletCustomerID(customerID) if err != nil { return nil, err } data, err := p.walletQuery.LegacyPoints(ctx, id) if err != nil { return nil, fmt.Errorf("failed to get customer points: %w", err) } return &models.GetCustomerPointsResponse{ Status: "SUCCESS", Message: "Customer points retrieved successfully.", Data: data, }, nil } func (p *CustomerPointsProcessor) GetCustomerTotalTokensAPI(ctx context.Context, customerID string) (*models.GetCustomerTokensResponse, error) { id, err := parseWalletCustomerID(customerID) if err != nil { return nil, err } data, err := p.walletQuery.LegacyTokens(ctx, id) if err != nil { return nil, fmt.Errorf("failed to get customer tokens: %w", err) } return &models.GetCustomerTokensResponse{ Status: "SUCCESS", Message: "Customer tokens retrieved successfully.", Data: data, }, nil } func (p *CustomerPointsProcessor) GetCustomerWalletAPI(ctx context.Context, customerID string) (*models.GetCustomerWalletResponse, error) { id, err := parseWalletCustomerID(customerID) if err != nil { return nil, err } data, err := p.walletQuery.Summary(ctx, id) if err != nil { return nil, fmt.Errorf("failed to get customer wallet: %w", err) } return &models.GetCustomerWalletResponse{ Status: "SUCCESS", Message: "Customer wallet retrieved successfully.", Data: data, }, nil } func (p *CustomerPointsProcessor) GetCustomerWalletTransactionsAPI(ctx context.Context, customerID string, query models.ListCustomerWalletTransactionsQuery) (*models.PaginatedResponse[models.CustomerWalletTransaction], error) { id, err := parseWalletCustomerID(customerID) if err != nil { return nil, err } return p.walletQuery.Transactions(ctx, id, query) } func parseWalletCustomerID(customerID string) (uuid.UUID, error) { id, err := uuid.Parse(customerID) if err != nil { return uuid.Nil, fmt.Errorf("%w: invalid customer id", ErrInvalidWalletQuery) } return id, 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, }, }, nil }