package repository import ( "context" "database/sql" "errors" "fmt" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/jackc/pgx/v5/pgtype" ) type VirtualGameRepository interface { CreateVirtualGameSession(ctx context.Context, session *domain.VirtualGameSession) error GetVirtualGameSessionByToken(ctx context.Context, token string) (*domain.VirtualGameSession, error) UpdateVirtualGameSessionStatus(ctx context.Context, id int64, status string) error CreateVirtualGameTransaction(ctx context.Context, tx *domain.VirtualGameTransaction) error GetVirtualGameTransactionByExternalID(ctx context.Context, externalID string) (*domain.VirtualGameTransaction, error) UpdateVirtualGameTransactionStatus(ctx context.Context, id int64, status string) error GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) } type VirtualGameRepo struct { store *Store } // GetGameCounts implements VirtualGameRepository. // func (r *VirtualGameRepo) GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total int64, active int64, inactive int64, err error) { // panic("unimplemented") // } func NewVirtualGameRepository(store *Store) VirtualGameRepository { return &VirtualGameRepo{store: store} } func (r *VirtualGameRepo) CreateVirtualGameSession(ctx context.Context, session *domain.VirtualGameSession) error { params := dbgen.CreateVirtualGameSessionParams{ UserID: session.UserID, GameID: session.GameID, SessionToken: session.SessionToken, Currency: session.Currency, Status: session.Status, ExpiresAt: pgtype.Timestamptz{Time: session.ExpiresAt, Valid: true}, } _, err := r.store.queries.CreateVirtualGameSession(ctx, params) return err } func (r *VirtualGameRepo) GetVirtualGameSessionByToken(ctx context.Context, token string) (*domain.VirtualGameSession, error) { dbSession, err := r.store.queries.GetVirtualGameSessionByToken(ctx, token) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil } return nil, err } return &domain.VirtualGameSession{ ID: dbSession.ID, UserID: dbSession.UserID, GameID: dbSession.GameID, SessionToken: dbSession.SessionToken, Currency: dbSession.Currency, Status: dbSession.Status, CreatedAt: dbSession.CreatedAt.Time, UpdatedAt: dbSession.UpdatedAt.Time, ExpiresAt: dbSession.ExpiresAt.Time, }, nil } func (r *VirtualGameRepo) UpdateVirtualGameSessionStatus(ctx context.Context, id int64, status string) error { return r.store.queries.UpdateVirtualGameSessionStatus(ctx, dbgen.UpdateVirtualGameSessionStatusParams{ ID: id, Status: status, }) } func (r *VirtualGameRepo) CreateVirtualGameTransaction(ctx context.Context, tx *domain.VirtualGameTransaction) error { params := dbgen.CreateVirtualGameTransactionParams{ SessionID: tx.SessionID, UserID: tx.UserID, WalletID: tx.WalletID, TransactionType: tx.TransactionType, Amount: tx.Amount, Currency: tx.Currency, ExternalTransactionID: tx.ExternalTransactionID, Status: tx.Status, } _, err := r.store.queries.CreateVirtualGameTransaction(ctx, params) return err } func (r *VirtualGameRepo) GetVirtualGameTransactionByExternalID(ctx context.Context, externalID string) (*domain.VirtualGameTransaction, error) { dbTx, err := r.store.queries.GetVirtualGameTransactionByExternalID(ctx, externalID) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil } return nil, err } return &domain.VirtualGameTransaction{ ID: dbTx.ID, SessionID: dbTx.SessionID, UserID: dbTx.UserID, WalletID: dbTx.WalletID, TransactionType: dbTx.TransactionType, Amount: dbTx.Amount, Currency: dbTx.Currency, ExternalTransactionID: dbTx.ExternalTransactionID, Status: dbTx.Status, CreatedAt: dbTx.CreatedAt.Time, UpdatedAt: dbTx.UpdatedAt.Time, }, nil } func (r *VirtualGameRepo) UpdateVirtualGameTransactionStatus(ctx context.Context, id int64, status string) error { return r.store.queries.UpdateVirtualGameTransactionStatus(ctx, dbgen.UpdateVirtualGameTransactionStatusParams{ ID: id, Status: status, }) } func (r *VirtualGameRepo) GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) { query := `SELECT COUNT(*) as total, COUNT(CASE WHEN is_active = true THEN 1 END) as active, COUNT(CASE WHEN is_active = false THEN 1 END) as inactive FROM virtual_games` args := []interface{}{} argPos := 1 // Add filters if provided if filter.StartTime.Valid { query += fmt.Sprintf(" WHERE created_at >= $%d", argPos) args = append(args, filter.StartTime.Value) argPos++ } if filter.EndTime.Valid { query += fmt.Sprintf(" AND created_at <= $%d", argPos) args = append(args, filter.EndTime.Value) argPos++ } row := r.store.conn.QueryRow(ctx, query, args...) err = row.Scan(&total, &active, &inactive) if err != nil { return 0, 0, 0, fmt.Errorf("failed to get game counts: %w", err) } return total, active, inactive, nil }