package handlers import ( "context" "errors" "fmt" "log" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame/veli" "github.com/gofiber/fiber/v2" ) // GetProviders godoc // @Summary Get game providers // @Description Retrieves the list of VeliGames providers // @Tags Virtual Games - VeliGames // @Accept json // @Produce json // @Param request body domain.ProviderRequest true "Brand ID and paging options" // @Success 200 {object} domain.Response{data=[]domain.ProviderResponse} // @Failure 400 {object} domain.ErrorResponse // @Failure 401 {object} domain.ErrorResponse // @Failure 500 {object} domain.ErrorResponse // @Router /api/v1/veli/providers [post] func (h *Handler) GetProviders(c *fiber.Ctx) error { var req domain.ProviderRequest if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Failed to retrieve providers", Error: err.Error(), }) } if req.BrandID == "" { req.BrandID = h.Cfg.VeliGames.BrandID // default } res, err := h.veliVirtualGameSvc.GetProviders(context.Background(), req) if err != nil { log.Println("GetProviders error:", err) return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{ Message: "Failed to retrieve providers", Error: err.Error(), }) } return c.Status(fiber.StatusOK).JSON(domain.Response{ Message: "Providers retrieved successfully", Data: res, StatusCode: 200, Success: true, }) } // GetGamesByProvider godoc // @Summary Get games by provider // @Description Retrieves games for the specified provider // @Tags Virtual Games - VeliGames // @Accept json // @Produce json // @Param request body domain.GameListRequest true "Brand and Provider ID" // @Success 200 {object} domain.Response // @Failure 400 {object} domain.ErrorResponse // @Failure 502 {object} domain.ErrorResponse // @Router /api/v1/veli/games-list [post] func (h *Handler) GetGamesByProvider(c *fiber.Ctx) error { var req domain.GameListRequest if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Invalid request body", Error: err.Error(), }) } if req.BrandID == "" { req.BrandID = h.Cfg.VeliGames.BrandID } res, err := h.veliVirtualGameSvc.GetGames(context.Background(), req) if err != nil { log.Println("GetGames error:", err) return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{ Message: "Failed to retrieve games", Error: err.Error(), }) } return c.Status(fiber.StatusOK).JSON(domain.Response{ Message: "Games retrieved successfully", Data: res, StatusCode: fiber.StatusOK, Success: true, }) } // StartGame godoc // @Summary Start a real game session // @Description Starts a real VeliGames session with the given player and game info // @Tags Virtual Games - VeliGames // @Accept json // @Produce json // @Param request body domain.GameStartRequest true "Start game input" // @Success 200 {object} domain.Response{data=domain.GameStartResponse} // @Failure 400 {object} domain.ErrorResponse // @Failure 502 {object} domain.ErrorResponse // @Router /api/v1/veli/start-game [post] func (h *Handler) StartGame(c *fiber.Ctx) error { userId, ok := c.Locals("user_id").(int64) if !ok { return c.Status(fiber.StatusUnauthorized).JSON(domain.ErrorResponse{ Error: "missing user id", Message: "Unauthorized", }) } var req domain.GameStartRequest if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Invalid request body", Error: err.Error(), }) } req.PlayerID = fmt.Sprintf("%d", userId) if req.BrandID == "" { req.BrandID = h.Cfg.VeliGames.BrandID } res, err := h.veliVirtualGameSvc.StartGame(context.Background(), req) if err != nil { log.Println("StartGame error:", err) return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{ Message: "Failed to start game", Error: err.Error(), }) } return c.Status(fiber.StatusOK).JSON(domain.Response{ Message: "Game started successfully", Data: res, StatusCode: fiber.StatusOK, Success: true, }) } // StartDemoGame godoc // @Summary Start a demo game session // @Description Starts a demo session of the specified game (must support demo mode) // @Tags Virtual Games - VeliGames // @Accept json // @Produce json // @Param request body domain.DemoGameRequest true "Start demo game input" // @Success 200 {object} domain.Response{data=domain.GameStartResponse} // @Failure 400 {object} domain.ErrorResponse // @Failure 502 {object} domain.ErrorResponse // @Router /api/v1/veli/start-demo-game [post] func (h *Handler) StartDemoGame(c *fiber.Ctx) error { var req domain.DemoGameRequest if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Invalid request body", Error: err.Error(), }) } if req.BrandID == "" { req.BrandID = h.Cfg.VeliGames.BrandID } res, err := h.veliVirtualGameSvc.StartDemoGame(context.Background(), req) if err != nil { log.Println("StartDemoGame error:", err) return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{ Message: "Failed to start demo game", Error: err.Error(), }) } return c.Status(fiber.StatusOK).JSON(domain.Response{ Message: "Demo game started successfully", Data: res, StatusCode: fiber.StatusOK, Success: true, }) } func (h *Handler) GetBalance(c *fiber.Ctx) error { var req domain.BalanceRequest if err := c.BodyParser(&req); err != nil { // return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Invalid request body", Error: err.Error(), }) } // Optionally verify signature here... balance, err := h.veliVirtualGameSvc.GetBalance(c.Context(), req) if err != nil { // return fiber.NewError(fiber.StatusInternalServerError, err.Error()) return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Failed to retrieve balance", Error: err.Error(), }) } return c.JSON(balance) } func (h *Handler) PlaceBet(c *fiber.Ctx) error { var req domain.BetRequest if err := c.BodyParser(&req); err != nil { // return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Invalid request body", Error: err.Error(), }) } // Signature check optional here res, err := h.veliVirtualGameSvc.ProcessBet(c.Context(), req) if err != nil { if errors.Is(err, veli.ErrDuplicateTransaction) { return fiber.NewError(fiber.StatusConflict, "DUPLICATE_TRANSACTION") } return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Failed to process bet", Error: err.Error(), }) // return fiber.NewError(fiber.StatusBadRequest, err.Error()) } return c.JSON(res) } func (h *Handler) RegisterWin(c *fiber.Ctx) error { var req domain.WinRequest if err := c.BodyParser(&req); err != nil { // return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Invalid request body", Error: err.Error(), }) } res, err := h.veliVirtualGameSvc.ProcessWin(c.Context(), req) if err != nil { if errors.Is(err, veli.ErrDuplicateTransaction) { return fiber.NewError(fiber.StatusConflict, "DUPLICATE_TRANSACTION") } // return fiber.NewError(fiber.StatusInternalServerError, err.Error()) return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{ Message: "Failed to process win", Error: err.Error(), }) } return c.JSON(res) } func (h *Handler) CancelTransaction(c *fiber.Ctx) error { var req domain.CancelRequest if err := c.BodyParser(&req); err != nil { // return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Invalid request body", Error: err.Error(), }) } res, err := h.veliVirtualGameSvc.ProcessCancel(c.Context(), req) if err != nil { if errors.Is(err, veli.ErrDuplicateTransaction) { return fiber.NewError(fiber.StatusConflict, "DUPLICATE_TRANSACTION") } // return fiber.NewError(fiber.StatusInternalServerError, err.Error()) return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Failed to process cancel", Error: err.Error(), }) } return c.JSON(res) } // GetGamingActivity godoc // @Summary Get Veli Gaming Activity // @Description Retrieves successfully processed gaming activity transactions (BET, WIN, CANCEL) from Veli Games // @Tags Virtual Games - VeliGames // @Accept json // @Produce json // @Param request body domain.GamingActivityRequest true "Gaming Activity Request" // @Success 200 {object} domain.Response{data=domain.GamingActivityResponse} // @Failure 400 {object} domain.ErrorResponse // @Failure 500 {object} domain.ErrorResponse // @Router /api/v1/veli/gaming-activity [post] func (h *Handler) GetGamingActivity(c *fiber.Ctx) error { var req domain.GamingActivityRequest if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Invalid request payload", Error: err.Error(), }) } resp, err := h.veliVirtualGameSvc.GetGamingActivity(c.Context(), req) if err != nil { log.Println("GetGamingActivity error:", err) return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{ Message: "Failed to retrieve gaming activity", Error: err.Error(), }) } return c.Status(fiber.StatusOK).JSON(domain.Response{ Message: "Gaming activity retrieved successfully", Data: resp, StatusCode: fiber.StatusOK, Success: true, }) } // GetHugeWins godoc // @Summary Get Veli Huge Wins // @Description Retrieves huge win transactions based on brand configuration (e.g. win > 10000 USD or 100x bet) // @Tags Virtual Games - VeliGames // @Accept json // @Produce json // @Param request body domain.HugeWinsRequest true "Huge Wins Request" // @Success 200 {object} domain.Response{data=domain.HugeWinsResponse} // @Failure 400 {object} domain.ErrorResponse // @Failure 500 {object} domain.ErrorResponse // @Router /api/v1/veli/huge-wins [post] func (h *Handler) GetHugeWins(c *fiber.Ctx) error { var req domain.HugeWinsRequest if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ Message: "Invalid request payload", Error: err.Error(), }) } resp, err := h.veliVirtualGameSvc.GetHugeWins(c.Context(), req) if err != nil { log.Println("GetHugeWins error:", err) return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{ Message: "Failed to retrieve huge wins", Error: err.Error(), }) } return c.Status(fiber.StatusOK).JSON(domain.Response{ Message: "Huge wins retrieved successfully", Data: resp, StatusCode: fiber.StatusOK, Success: true, }) }