Yimaru-BackEnd/internal/repository/virtual_game.go

317 lines
11 KiB
Go

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 {
CountVirtualGameProviders(ctx context.Context) (int64, error)
CreateVirtualGameProvider(ctx context.Context, arg dbgen.CreateVirtualGameProviderParams) (dbgen.VirtualGameProvider, error)
DeleteVirtualGameProvider(ctx context.Context, providerID string) error
GetVirtualGameProviderByID(ctx context.Context, providerID string) (dbgen.VirtualGameProvider, error)
ListVirtualGameProviders(ctx context.Context, limit, offset int32) ([]dbgen.VirtualGameProvider, error)
UpdateVirtualGameProviderEnabled(ctx context.Context, providerID string, enabled bool) (dbgen.VirtualGameProvider, error)
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
// WithTransaction(ctx context.Context, fn func(ctx context.Context) error) error
AddFavoriteGame(ctx context.Context, userID, gameID int64) error
RemoveFavoriteGame(ctx context.Context, userID, gameID int64) error
ListFavoriteGames(ctx context.Context, userID int64) ([]int64, error)
GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
GetUserGameHistory(ctx context.Context, userID int64) ([]domain.VirtualGameHistory, error)
CreateVirtualGameHistory(ctx context.Context, his *domain.VirtualGameHistory) 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 convertDBVirtualGameProvider(p dbgen.VirtualGameProvider) domain.VirtualGameProvider {
// var logoDark *string
// if p.LogoDark.Valid {
// logoDark = &p.LogoDark.String
// }
// var logoLight *string
// if p.LogoLight.Valid {
// logoLight = &p.LogoLight.String
// }
// return domain.VirtualGameProvider{
// // ID: p.ID,
// ProviderID: p.ProviderID,
// ProviderName: p.ProviderName,
// LogoDark: logoDark,
// LogoLight: logoLight,
// Enabled: p.Enabled,
// CreatedAt: p.CreatedAt.Time,
// UpdatedAt: &p.UpdatedAt.Time,
// }
// }
func ConvertCreateVirtualGameProvider(p domain.VirtualGameProvider) dbgen.CreateVirtualGameProviderParams {
return dbgen.CreateVirtualGameProviderParams{
ProviderID: p.ProviderID,
ProviderName: p.ProviderName,
LogoDark: pgtype.Text{String: func() string {
if p.LogoDark != nil {
return *p.LogoDark
}
return ""
}(), Valid: p.LogoDark != nil},
LogoLight: pgtype.Text{String: func() string {
if p.LogoLight != nil {
return *p.LogoLight
}
return ""
}(), Valid: p.LogoLight != nil},
Enabled: p.Enabled,
// CreatedAt: time.Now(),
}
}
func NewVirtualGameRepository(store *Store) VirtualGameRepository {
return &VirtualGameRepo{store: store}
}
func (r *VirtualGameRepo) CreateVirtualGameProvider(ctx context.Context, arg dbgen.CreateVirtualGameProviderParams) (dbgen.VirtualGameProvider, error) {
return r.store.queries.CreateVirtualGameProvider(ctx, arg)
}
func (r *VirtualGameRepo) DeleteVirtualGameProvider(ctx context.Context, providerID string) error {
return r.store.queries.DeleteVirtualGameProvider(ctx, providerID)
}
func (r *VirtualGameRepo) GetVirtualGameProviderByID(ctx context.Context, providerID string) (dbgen.VirtualGameProvider, error) {
return r.store.queries.GetVirtualGameProviderByID(ctx, providerID)
}
func (r *VirtualGameRepo) ListVirtualGameProviders(ctx context.Context, limit, offset int32) ([]dbgen.VirtualGameProvider, error) {
args := dbgen.ListVirtualGameProvidersParams{
Limit: limit,
Offset: offset,
}
return r.store.queries.ListVirtualGameProviders(ctx, args)
}
func (r *VirtualGameRepo) UpdateVirtualGameProviderEnabled(ctx context.Context, providerID string, enabled bool) (dbgen.VirtualGameProvider, error) {
params := dbgen.UpdateVirtualGameProviderEnabledParams{
ProviderID: providerID,
Enabled: enabled,
}
return r.store.queries.UpdateVirtualGameProviderEnabled(ctx, params)
}
func (r *VirtualGameRepo) AddFavoriteGame(ctx context.Context, userID, gameID int64) error {
params := dbgen.AddFavoriteGameParams{
UserID: userID,
GameID: gameID,
}
return r.store.queries.AddFavoriteGame(ctx, params)
}
func (r *VirtualGameRepo) RemoveFavoriteGame(ctx context.Context, userID, gameID int64) error {
params := dbgen.RemoveFavoriteGameParams{
UserID: userID,
GameID: gameID,
}
return r.store.queries.RemoveFavoriteGame(ctx, params)
}
func (r *VirtualGameRepo) ListFavoriteGames(ctx context.Context, userID int64) ([]int64, error) {
return r.store.queries.ListFavoriteGames(ctx, userID)
}
func (r *VirtualGameRepo) CountVirtualGameProviders(ctx context.Context) (int64, error) {
return r.store.queries.CountVirtualGameProviders(ctx)
}
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) CreateVirtualGameHistory(ctx context.Context, his *domain.VirtualGameHistory) error {
params := dbgen.CreateVirtualGameHistoryParams{
SessionID: pgtype.Text{String: his.SessionID, Valid: true},
UserID: his.UserID,
// WalletID: pgtype.Int8{Int64: *his.WalletID, Valid: true},
TransactionType: his.TransactionType,
Amount: his.Amount,
Currency: his.Currency,
ExternalTransactionID: his.ExternalTransactionID,
Status: his.Status,
}
_, err := r.store.queries.CreateVirtualGameHistory(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
}
func (r *VirtualGameRepo) GetUserGameHistory(ctx context.Context, userID int64) ([]domain.VirtualGameHistory, error) {
query := `SELECT game_id FROM virtual_game_histories WHERE user_id = $1 AND transaction_type = 'BET' ORDER BY created_at DESC LIMIT 100`
rows, err := r.store.conn.Query(ctx, query, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var history []domain.VirtualGameHistory
for rows.Next() {
var tx domain.VirtualGameHistory
if err := rows.Scan(&tx.GameID); err == nil {
history = append(history, tx)
}
}
return history, nil
}
// func (r *VirtualGameRepo) WithTransaction(ctx context.Context, fn func(ctx context.Context) error) error {
// _, tx, err := r.store.BeginTx(ctx)
// if err != nil {
// return err
// }
// txCtx := context.WithValue(ctx, contextTxKey, tx)
// defer func() {
// if p := recover(); p != nil {
// tx.Rollback(ctx)
// panic(p)
// }
// }()
// err = fn(txCtx)
// if err != nil {
// tx.Rollback(ctx)
// return err
// }
// return tx.Commit(ctx)
// }