package repository import ( "context" "fmt" "apskel-pos-be/internal/entities" "github.com/google/uuid" "gorm.io/gorm" ) type GamePlayRepository interface { Create(ctx context.Context, gamePlay *entities.GamePlay) error GetByID(ctx context.Context, id uuid.UUID) (*entities.GamePlay, error) List(ctx context.Context, offset, limit int, search string, gameID, customerID, prizeID *uuid.UUID, sortBy, sortOrder string) ([]*entities.GamePlay, int64, error) GetByCustomerID(ctx context.Context, customerID uuid.UUID, limit int) ([]*entities.GamePlay, error) GetByGameID(ctx context.Context, gameID uuid.UUID, limit int) ([]*entities.GamePlay, error) CountByCustomerID(ctx context.Context, customerID uuid.UUID) (int64, error) CountByGameID(ctx context.Context, gameID uuid.UUID) (int64, error) } type gamePlayRepository struct { db *gorm.DB } func NewGamePlayRepository(db *gorm.DB) GamePlayRepository { return &gamePlayRepository{ db: db, } } func (r *gamePlayRepository) Create(ctx context.Context, gamePlay *entities.GamePlay) error { if err := r.db.WithContext(ctx).Create(gamePlay).Error; err != nil { return fmt.Errorf("failed to create game play: %w", err) } return nil } func (r *gamePlayRepository) GetByID(ctx context.Context, id uuid.UUID) (*entities.GamePlay, error) { var gamePlay entities.GamePlay err := r.db.WithContext(ctx). Preload("Game"). Preload("Customer"). Preload("Prize"). First(&gamePlay, "id = ?", id).Error if err != nil { if err == gorm.ErrRecordNotFound { return nil, fmt.Errorf("game play not found") } return nil, fmt.Errorf("failed to get game play: %w", err) } return &gamePlay, nil } func (r *gamePlayRepository) List(ctx context.Context, offset, limit int, search string, gameID, customerID, prizeID *uuid.UUID, sortBy, sortOrder string) ([]*entities.GamePlay, int64, error) { var gamePlays []*entities.GamePlay var total int64 query := r.db.WithContext(ctx).Model(&entities.GamePlay{}) // Apply filters if search != "" { query = query.Where("random_seed ILIKE ?", "%"+search+"%") } if gameID != nil { query = query.Where("game_id = ?", *gameID) } if customerID != nil { query = query.Where("customer_id = ?", *customerID) } if prizeID != nil { query = query.Where("prize_id = ?", *prizeID) } // Count total records if err := query.Count(&total).Error; err != nil { return nil, 0, fmt.Errorf("failed to count game plays: %w", err) } // Apply sorting if sortBy != "" { if sortOrder == "desc" { query = query.Order(fmt.Sprintf("%s DESC", sortBy)) } else { query = query.Order(fmt.Sprintf("%s ASC", sortBy)) } } else { query = query.Order("created_at DESC") } // Apply pagination and preload relations err := query. Preload("Game"). Preload("Customer"). Preload("Prize"). Offset(offset). Limit(limit). Find(&gamePlays).Error if err != nil { return nil, 0, fmt.Errorf("failed to list game plays: %w", err) } return gamePlays, total, nil } func (r *gamePlayRepository) GetByCustomerID(ctx context.Context, customerID uuid.UUID, limit int) ([]*entities.GamePlay, error) { var gamePlays []*entities.GamePlay query := r.db.WithContext(ctx). Where("customer_id = ?", customerID). Preload("Game"). Preload("Prize"). Order("created_at DESC") if limit > 0 { query = query.Limit(limit) } err := query.Find(&gamePlays).Error if err != nil { return nil, fmt.Errorf("failed to get game plays by customer ID: %w", err) } return gamePlays, nil } func (r *gamePlayRepository) GetByGameID(ctx context.Context, gameID uuid.UUID, limit int) ([]*entities.GamePlay, error) { var gamePlays []*entities.GamePlay query := r.db.WithContext(ctx). Where("game_id = ?", gameID). Preload("Customer"). Preload("Prize"). Order("created_at DESC") if limit > 0 { query = query.Limit(limit) } err := query.Find(&gamePlays).Error if err != nil { return nil, fmt.Errorf("failed to get game plays by game ID: %w", err) } return gamePlays, nil } func (r *gamePlayRepository) CountByCustomerID(ctx context.Context, customerID uuid.UUID) (int64, error) { var count int64 err := r.db.WithContext(ctx). Model(&entities.GamePlay{}). Where("customer_id = ?", customerID). Count(&count).Error if err != nil { return 0, fmt.Errorf("failed to count game plays by customer ID: %w", err) } return count, nil } func (r *gamePlayRepository) CountByGameID(ctx context.Context, gameID uuid.UUID) (int64, error) { var count int64 err := r.db.WithContext(ctx). Model(&entities.GamePlay{}). Where("game_id = ?", gameID). Count(&count).Error if err != nil { return 0, fmt.Errorf("failed to count game plays by game ID: %w", err) } return count, nil }