Yimaru-BackEnd/internal/services/virtualGame/atlas/service.go

325 lines
10 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package atlas
import (
"context"
"errors"
"fmt"
"strconv"
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/ports"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
virtualgameservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
)
type Service struct {
virtualGameSvc virtualgameservice.VirtualGameService
repo repository.VirtualGameRepository
client *Client
walletSvc *wallet.Service
transfetStore ports.TransferStore
cfg *config.Config
}
func New(virtualGameSvc virtualgameservice.VirtualGameService, repo repository.VirtualGameRepository, client *Client, walletSvc *wallet.Service, transferStore ports.TransferStore, cfg *config.Config) *Service {
return &Service{
virtualGameSvc: virtualGameSvc,
repo: repo,
client: client,
walletSvc: walletSvc,
transfetStore: transferStore,
cfg: cfg,
}
}
func (s *Service) InitGame(ctx context.Context, req domain.AtlasGameInitRequest) (*domain.AtlasGameInitResponse, error) {
body := map[string]any{
"game": req.Game,
"partner_id": s.client.PartnerID,
"casino_id": s.client.CasinoID,
"language": req.Language,
"currency": req.Currency,
"player_id": req.PlayerID,
}
// 3. Call the Atlas client
var res domain.AtlasGameInitResponse
if err := s.client.post(ctx, "/init", body, &res); err != nil {
return nil, fmt.Errorf("failed to initialize game: %w", err)
}
return &res, nil
}
func (s *Service) GetUserData(ctx context.Context, req domain.AtlasGetUserDataRequest) (*domain.AtlasGetUserDataResponse, error) {
// 1. Validate casino_id and hash if needed
if req.CasinoID != s.client.CasinoID {
return nil, fmt.Errorf("invalid casino_id")
}
// 2. Fetch player from DB
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid playerID: %w", err)
}
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
if err != nil {
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
}
// 4. Build response
res := &domain.AtlasGetUserDataResponse{
PlayerID: req.PlayerID,
Balance: float64(wallet.RegularBalance),
}
return res, nil
}
func (s *Service) ProcessBet(ctx context.Context, req domain.AtlasBetRequest) (*domain.AtlasBetResponse, error) {
if req.CasinoID != s.client.CasinoID {
return nil, fmt.Errorf("invalid casino_id")
}
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid playerID: %w", err)
}
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
if err != nil {
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
}
// if player == nil {
// return nil, ErrPlayerNotFound
// }
// 3. Check for duplicate transaction
// exists, err := s.repo.TransactionExists(ctx, req.TransactionID)
// if err != nil {
// return nil, fmt.Errorf("failed to check transaction: %w", err)
// }
// if exists {
// return nil, ErrDuplicateTransaction
// }
// // 4. Get current balance
// balance, err := s.walletSvc.GetBalance(ctx, req.PlayerID)
// if err != nil {
// return nil, fmt.Errorf("failed to fetch wallet balance: %w", err)
// }
// 5. Ensure sufficient balance
if float64(wallet.RegularBalance) < req.Amount {
return nil, domain.ErrInsufficientBalance
}
// 6. Deduct amount from wallet (record transaction)
_, err = s.walletSvc.DeductFromWallet(ctx, wallet.ID, domain.Currency(req.Amount), domain.ValidInt64{}, domain.PaymentMethod(domain.DEPOSIT), "")
if err != nil {
return nil, fmt.Errorf("failed to debit wallet: %w", err)
}
// 7. Save transaction record to DB (optional but recommended)
// if err := s.repo.SaveBetTransaction(ctx, req); err != nil {
// // log warning but dont fail response to Atlas
// fmt.Printf("warning: failed to save bet transaction: %v\n", err)
// }
// 8. Build response
res := &domain.AtlasBetResponse{
PlayerID: req.PlayerID,
Balance: float64(wallet.RegularBalance) - req.Amount,
}
return res, nil
}
func (s *Service) ProcessBetWin(ctx context.Context, req domain.AtlasBetWinRequest) (*domain.AtlasBetWinResponse, error) {
if req.CasinoID != s.client.CasinoID {
return nil, fmt.Errorf("invalid casino_id")
}
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid playerID: %w", err)
}
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
if err != nil {
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
}
// 5. Ensure sufficient balance
if float64(wallet.RegularBalance) < req.BetAmount {
return nil, domain.ErrInsufficientBalance
}
// 6. Deduct amount from wallet (record transaction)
_, err = s.walletSvc.DeductFromWallet(ctx, wallet.ID, domain.Currency(req.BetAmount), domain.ValidInt64{}, domain.PaymentMethod(domain.DEPOSIT), "")
if err != nil {
return nil, fmt.Errorf("failed to debit wallet: %w", err)
}
if req.WinAmount > 0 {
_, err = s.walletSvc.AddToWallet(ctx, wallet.ID, domain.Currency(req.WinAmount), domain.ValidInt64{}, domain.PaymentMethod(domain.DEPOSIT), domain.PaymentDetails{}, "")
if err != nil {
return nil, fmt.Errorf("failed to credit wallet: %w", err)
}
}
// 8. Build response
res := &domain.AtlasBetWinResponse{
PlayerID: req.PlayerID,
Balance: float64(wallet.RegularBalance) - req.BetAmount + req.WinAmount,
}
return res, nil
}
func (s *Service) ProcessRoundResult(ctx context.Context, req domain.RoundResultRequest) (*domain.RoundResultResponse, error) {
if req.PlayerID == "" || req.TransactionID == "" {
return nil, errors.New("missing player_id or transaction_id")
}
// Credit player with win amount if > 0
if req.Amount > 0 {
// This will credit player's balance
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid playerID: %w", err)
}
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
if err != nil {
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
}
_, err = s.walletSvc.AddToWallet(ctx, wallet.ID, domain.Currency(req.Amount), domain.ValidInt64{}, domain.PaymentMethod(domain.DEPOSIT), domain.PaymentDetails{}, "")
if err != nil {
return nil, fmt.Errorf("failed to credit wallet: %w", err)
}
}
return &domain.RoundResultResponse{Success: true}, nil
}
func (s *Service) ProcessRollBack(ctx context.Context, req domain.RollbackRequest) (*domain.RollbackResponse, error) {
if req.PlayerID == "" || req.BetTransactionID == "" {
return nil, errors.New("missing player_id or transaction_id")
}
// Credit player with win amount if > 0
// This will credit player's balance
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid playerID: %w", err)
}
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
if err != nil {
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
}
transfer, err := s.transfetStore.GetTransferByReference(ctx, req.BetTransactionID)
if err != nil {
return nil, fmt.Errorf("failed to fetch transfer for reference %s: %w", req.BetTransactionID, err)
}
_, err = s.walletSvc.AddToWallet(ctx, wallet.ID, domain.Currency(transfer.Amount), domain.ValidInt64{}, domain.PaymentMethod(domain.DEPOSIT), domain.PaymentDetails{}, "")
if err != nil {
return nil, fmt.Errorf("failed to credit wallet: %w", err)
}
err = s.transfetStore.UpdateTransferStatus(ctx, transfer.ID, string(domain.STATUS_CANCELLED))
if err != nil {
return nil, fmt.Errorf("failed to update transfer status: %w", err)
}
err = s.transfetStore.UpdateTransferVerification(ctx, transfer.ID, true)
if err != nil {
return nil, fmt.Errorf("failed to update transfer verification: %w", err)
}
return &domain.RollbackResponse{Success: true}, nil
}
func (s *Service) CreateFreeSpin(ctx context.Context, req domain.FreeSpinRequest) (*domain.FreeSpinResponse, error) {
body := map[string]any{
"casino_id": s.client.CasinoID,
"freespins_count": req.FreeSpinsCount,
"end_date": req.EndDate,
"player_id": req.PlayerID,
}
// 3. Call the Atlas client
var res domain.FreeSpinResponse
if err := s.client.post(ctx, "/freespin", body, &res); err != nil {
return nil, fmt.Errorf("failed to create free spin: %w", err)
}
return &res, nil
}
func (s *Service) ProcessFreeSpinResult(ctx context.Context, req domain.FreeSpinResultRequest) (*domain.FreeSpinResultResponse, error) {
if req.PlayerID == "" || req.TransactionID == "" {
return nil, errors.New("missing player_id or transaction_id")
}
// Credit player with win amount if > 0
if req.Amount > 0 {
// This will credit player's balance
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid playerID: %w", err)
}
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
if err != nil {
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
}
_, err = s.walletSvc.AddToWallet(ctx, wallet.ID, domain.Currency(req.Amount), domain.ValidInt64{}, domain.PaymentMethod(domain.DEPOSIT), domain.PaymentDetails{}, "")
if err != nil {
return nil, fmt.Errorf("failed to credit wallet: %w", err)
}
}
return &domain.FreeSpinResultResponse{Success: true}, nil
}
func (s *Service) ProcessJackPot(ctx context.Context, req domain.JackpotRequest) (*domain.JackpotResponse, error) {
if req.PlayerID == "" || req.TransactionID == "" {
return nil, errors.New("missing player_id or transaction_id")
}
// Credit player with win amount if > 0
if req.Amount > 0 {
// This will credit player's balance
playerIDInt, err := strconv.ParseInt(req.PlayerID, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid playerID: %w", err)
}
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt)
if err != nil {
return nil, fmt.Errorf("failed to fetch walllets for player %d: %w", playerIDInt, err)
}
_, err = s.walletSvc.AddToWallet(ctx, wallet.ID, domain.Currency(req.Amount), domain.ValidInt64{}, domain.PaymentMethod(domain.DEPOSIT), domain.PaymentDetails{}, "")
if err != nil {
return nil, fmt.Errorf("failed to credit wallet: %w", err)
}
}
return &domain.JackpotResponse{Success: true}, nil
}