package handlers import ( "fmt" "strconv" "time" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/gofiber/fiber/v2" "go.uber.org/zap" ) func ParseLeagueIDFromQuery(c *fiber.Ctx) (domain.ValidInt64, error) { leagueIDQuery := c.Query("league_id") if leagueIDQuery != "" { leagueIDInt, err := strconv.ParseInt(leagueIDQuery, 10, 64) if err != nil { return domain.ValidInt64{}, fmt.Errorf("failed to parse league_id %v: %w", leagueIDQuery, err) } return domain.ValidInt64{ Value: leagueIDInt, Valid: true, }, nil } return domain.ValidInt64{}, nil } // @Summary Retrieve all upcoming events // @Description Retrieve all upcoming events from the database // @Tags prematch // @Accept json // @Produce json // @Param page query int false "Page number" // @Param page_size query int false "Page size" // @Param league_id query string false "League ID Filter" // @Param sport_id query string false "Sport ID Filter" // @Param cc query string false "Country Code Filter" // @Param first_start_time query string false "Start Time" // @Param last_start_time query string false "End Time" // @Success 200 {array} domain.BaseEvent // @Failure 500 {object} response.APIResponse // @Router /api/v1/events [get] func (h *Handler) GetAllEvents(c *fiber.Ctx) error { page := c.QueryInt("page", 1) pageSize := c.QueryInt("page_size", 10) limit := domain.ValidInt32{ Value: int32(pageSize), Valid: true, } offset := domain.ValidInt32{ Value: int32(page - 1), Valid: true, } leagueIDQuery := c.Query("league_id") var leagueID domain.ValidInt64 if leagueIDQuery != "" { leagueIDInt, err := strconv.ParseInt(leagueIDQuery, 10, 64) if err != nil { h.BadRequestLogger().Error("invalid league id", zap.String("league_id", leagueIDQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "invalid league id") } leagueID = domain.ValidInt64{ Value: leagueIDInt, Valid: true, } } // TODO: Go through the all the handler functions and change them into something like this // leagueID, err := ParseLeagueIDFromQuery(c) // if err != nil { // h.BadRequestLogger().Info("invalid league id", zap.Error(err)) // return fiber.NewError(fiber.StatusBadRequest, "invalid league id") // } sportIDQuery := c.Query("sport_id") var sportID domain.ValidInt32 if sportIDQuery != "" { sportIDint, err := strconv.Atoi(sportIDQuery) if err != nil { h.BadRequestLogger().Info("invalid sport id", zap.String("sportID", sportIDQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "invalid sport id") } sportID = domain.ValidInt32{ Value: int32(sportIDint), Valid: true, } } searchQuery := c.Query("query") searchString := domain.ValidString{ Value: searchQuery, Valid: searchQuery != "", } firstStartTimeQuery := c.Query("first_start_time") var firstStartTime domain.ValidTime if firstStartTimeQuery != "" { firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery) if err != nil { h.BadRequestLogger().Info("invalid start_time format", zap.String("first_start_time", firstStartTimeQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format") } firstStartTime = domain.ValidTime{ Value: firstStartTimeParsed, Valid: true, } } lastStartTimeQuery := c.Query("last_start_time") var lastStartTime domain.ValidTime if lastStartTimeQuery != "" { lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery) if err != nil { h.BadRequestLogger().Info("invalid last_start_time format", zap.String("last_start_time", lastStartTimeQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format") } lastStartTime = domain.ValidTime{ Value: lastStartTimeParsed, Valid: true, } } countryCodeQuery := c.Query("cc") countryCode := domain.ValidString{ Value: countryCodeQuery, Valid: countryCodeQuery != "", } isFeaturedQuery := c.Query("is_featured") var isFeatured domain.ValidBool if isFeaturedQuery != "" { isFeaturedParsed, err := strconv.ParseBool(isFeaturedQuery) if err != nil { h.BadRequestLogger().Error("Failed to parse isFeatured", zap.String("is_featured", isFeaturedQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_shop_bet") } isFeatured = domain.ValidBool{ Value: isFeaturedParsed, Valid: true, } } isActiveQuery := c.Query("is_active") var isActive domain.ValidBool if isActiveQuery != "" { isActiveParsed, err := strconv.ParseBool(isActiveQuery) if err != nil { h.BadRequestLogger().Error("Failed to parse isActive", zap.String("is_active", isActiveQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_active") } isActive = domain.ValidBool{ Value: isActiveParsed, Valid: true, } } statusQuery := c.Query("status") var eventStatus domain.ValidEventStatus if statusQuery != "" { eventStatusParsed, err := domain.ParseEventStatus(statusQuery) if err != nil { h.BadRequestLogger().Error("Failed to parse statusQuery", zap.String("status", statusQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "invalid event status string") } eventStatus = domain.ValidEventStatus{ Value: eventStatusParsed, Valid: true, } } events, total, err := h.eventSvc.GetAllEvents( c.Context(), domain.EventFilter{ SportID: sportID, LeagueID: leagueID, Query: searchString, FirstStartTime: firstStartTime, LastStartTime: lastStartTime, Limit: limit, Offset: offset, CountryCode: countryCode, Featured: isFeatured, Active: isActive, Status: eventStatus, }) // fmt.Printf("League ID: %v", leagueID) if err != nil { h.InternalServerErrorLogger().Error("Failed to retrieve all upcoming events", zap.Error(err), ) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } res := domain.ConvertEventResList(events) return response.WritePaginatedJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", res, nil, page, int(total)) } // @Summary Retrieve all upcoming events with settings // @Description Retrieve all upcoming events settings from the database // @Tags prematch // @Accept json // @Produce json // @Param page query int false "Page number" // @Param page_size query int false "Page size" // @Param league_id query string false "League ID Filter" // @Param sport_id query string false "Sport ID Filter" // @Param cc query string false "Country Code Filter" // @Param first_start_time query string false "Start Time" // @Param last_start_time query string false "End Time" // @Success 200 {array} domain.BaseEvent // @Failure 500 {object} response.APIResponse // @Router /api/v1/{tenant_slug}/events [get] func (h *Handler) GetTenantUpcomingEvents(c *fiber.Ctx) error { companyID := c.Locals("company_id").(domain.ValidInt64) if !companyID.Valid { h.BadRequestLogger().Error("invalid company id") return fiber.NewError(fiber.StatusBadRequest, "invalid company id") } page := c.QueryInt("page", 1) pageSize := c.QueryInt("page_size", 10) limit := domain.ValidInt32{ Value: int32(pageSize), Valid: true, } offset := domain.ValidInt32{ Value: int32(page - 1), Valid: true, } leagueIDQuery := c.Query("league_id") var leagueID domain.ValidInt64 if leagueIDQuery != "" { leagueIDInt, err := strconv.ParseInt(leagueIDQuery, 10, 64) if err != nil { h.BadRequestLogger().Error("invalid league id", zap.String("league_id", leagueIDQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "invalid league id") } leagueID = domain.ValidInt64{ Value: leagueIDInt, Valid: true, } } sportIDQuery := c.Query("sport_id") var sportID domain.ValidInt32 if sportIDQuery != "" { sportIDint, err := strconv.Atoi(sportIDQuery) if err != nil { h.BadRequestLogger().Info("invalid sport id", zap.String("sportID", sportIDQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "invalid sport id") } sportID = domain.ValidInt32{ Value: int32(sportIDint), Valid: true, } } searchQuery := c.Query("query") searchString := domain.ValidString{ Value: searchQuery, Valid: searchQuery != "", } firstStartTimeQuery := c.Query("first_start_time") var firstStartTime domain.ValidTime if firstStartTimeQuery != "" { firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery) if err != nil { h.BadRequestLogger().Info("invalid start_time format", zap.String("first_start_time", firstStartTimeQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format") } firstStartTime = domain.ValidTime{ Value: firstStartTimeParsed, Valid: true, } } else { firstStartTime = domain.ValidTime{ Value: time.Now(), Valid: true, } } lastStartTimeQuery := c.Query("last_start_time") var lastStartTime domain.ValidTime if lastStartTimeQuery != "" { lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery) if err != nil { h.BadRequestLogger().Info("invalid last_start_time format", zap.String("last_start_time", lastStartTimeQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format") } lastStartTime = domain.ValidTime{ Value: lastStartTimeParsed, Valid: true, } } countryCodeQuery := c.Query("cc") countryCode := domain.ValidString{ Value: countryCodeQuery, Valid: countryCodeQuery != "", } isFeaturedQuery := c.Query("is_featured") var isFeatured domain.ValidBool if isFeaturedQuery != "" { isFeaturedParsed, err := strconv.ParseBool(isFeaturedQuery) if err != nil { h.BadRequestLogger().Error("Failed to parse isFeatured", zap.String("is_featured", isFeaturedQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_shop_bet") } isFeatured = domain.ValidBool{ Value: isFeaturedParsed, Valid: true, } } events, total, err := h.eventSvc.GetEventsWithSettings( c.Context(), companyID.Value, domain.EventFilter{ SportID: sportID, LeagueID: leagueID, Query: searchString, FirstStartTime: firstStartTime, LastStartTime: lastStartTime, Limit: limit, Offset: offset, CountryCode: countryCode, Featured: isFeatured, Status: domain.ValidEventStatus{ Value: domain.STATUS_PENDING, Valid: true, }, IsLive: domain.ValidBool{ Value: false, Valid: true, }, Active: domain.ValidBool{ Value: true, Valid: true, }, }) // fmt.Printf("League ID: %v", leagueID) if err != nil { h.InternalServerErrorLogger().Error("Failed to retrieve all upcoming events", zap.Error(err), ) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } res := domain.ConvertEventWithSettingResList(events) return response.WritePaginatedJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", res, nil, page, int(total)) } // @Summary Retrieve all upcoming events with settings // @Description Retrieve all upcoming events settings from the database // @Tags prematch // @Accept json // @Produce json // @Param page query int false "Page number" // @Param page_size query int false "Page size" // @Param league_id query string false "League ID Filter" // @Param sport_id query string false "Sport ID Filter" // @Param cc query string false "Country Code Filter" // @Param first_start_time query string false "Start Time" // @Param last_start_time query string false "End Time" // @Success 200 {array} domain.BaseEvent // @Failure 500 {object} response.APIResponse // @Router /api/v1/{tenant_slug}/events [get] func (h *Handler) GetTenantEvents(c *fiber.Ctx) error { companyID := c.Locals("company_id").(domain.ValidInt64) if !companyID.Valid { h.BadRequestLogger().Error("invalid company id") return fiber.NewError(fiber.StatusBadRequest, "invalid company id") } page := c.QueryInt("page", 1) pageSize := c.QueryInt("page_size", 10) limit := domain.ValidInt32{ Value: int32(pageSize), Valid: true, } offset := domain.ValidInt32{ Value: int32(page - 1), Valid: true, } leagueIDQuery := c.Query("league_id") var leagueID domain.ValidInt64 if leagueIDQuery != "" { leagueIDInt, err := strconv.ParseInt(leagueIDQuery, 10, 64) if err != nil { h.BadRequestLogger().Error("invalid league id", zap.String("league_id", leagueIDQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "invalid league id") } leagueID = domain.ValidInt64{ Value: leagueIDInt, Valid: true, } } sportIDQuery := c.Query("sport_id") var sportID domain.ValidInt32 if sportIDQuery != "" { sportIDint, err := strconv.Atoi(sportIDQuery) if err != nil { h.BadRequestLogger().Info("invalid sport id", zap.String("sportID", sportIDQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "invalid sport id") } sportID = domain.ValidInt32{ Value: int32(sportIDint), Valid: true, } } searchQuery := c.Query("query") searchString := domain.ValidString{ Value: searchQuery, Valid: searchQuery != "", } firstStartTimeQuery := c.Query("first_start_time") var firstStartTime domain.ValidTime if firstStartTimeQuery != "" { firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery) if err != nil { h.BadRequestLogger().Info("invalid start_time format", zap.String("first_start_time", firstStartTimeQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format") } firstStartTime = domain.ValidTime{ Value: firstStartTimeParsed, Valid: true, } } lastStartTimeQuery := c.Query("last_start_time") var lastStartTime domain.ValidTime if lastStartTimeQuery != "" { lastStartTimeParsed, err := time.Parse(time.RFC3339, lastStartTimeQuery) if err != nil { h.BadRequestLogger().Info("invalid last_start_time format", zap.String("last_start_time", lastStartTimeQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Invalid start_time format") } lastStartTime = domain.ValidTime{ Value: lastStartTimeParsed, Valid: true, } } countryCodeQuery := c.Query("cc") countryCode := domain.ValidString{ Value: countryCodeQuery, Valid: countryCodeQuery != "", } isFeaturedQuery := c.Query("is_featured") var isFeatured domain.ValidBool if isFeaturedQuery != "" { isFeaturedParsed, err := strconv.ParseBool(isFeaturedQuery) if err != nil { h.BadRequestLogger().Error("Failed to parse isFeatured", zap.String("is_featured", isFeaturedQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_featured") } isFeatured = domain.ValidBool{ Value: isFeaturedParsed, Valid: true, } } isActiveQuery := c.Query("is_active") var isActive domain.ValidBool if isActiveQuery != "" { isActiveParsed, err := strconv.ParseBool(isActiveQuery) if err != nil { h.BadRequestLogger().Error("Failed to parse isActive", zap.String("is_active", isActiveQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "Failed to parse is_active") } isActive = domain.ValidBool{ Value: isActiveParsed, Valid: true, } } statusQuery := c.Query("status") var eventStatus domain.ValidEventStatus if statusQuery != "" { eventStatusParsed, err := domain.ParseEventStatus(statusQuery) if err != nil { h.BadRequestLogger().Error("Failed to parse statusQuery", zap.String("is_featured", isFeaturedQuery), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, "invalid event status string") } eventStatus = domain.ValidEventStatus{ Value: eventStatusParsed, Valid: true, } } events, total, err := h.eventSvc.GetEventsWithSettings( c.Context(), companyID.Value, domain.EventFilter{ SportID: sportID, LeagueID: leagueID, Query: searchString, FirstStartTime: firstStartTime, LastStartTime: lastStartTime, Limit: limit, Offset: offset, CountryCode: countryCode, Featured: isFeatured, Status: eventStatus, Active: isActive, }) // fmt.Printf("League ID: %v", leagueID) if err != nil { h.InternalServerErrorLogger().Error("Failed to retrieve all upcoming events", zap.Error(err), ) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } res := domain.ConvertEventWithSettingResList(events) return response.WritePaginatedJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", res, nil, page, int(total)) } type TopLeaguesRes struct { Leagues []TopLeague `json:"leagues"` } type TopLeague struct { LeagueID int64 `json:"league_id"` LeagueName string `json:"league_name"` LeagueCC string `json:"league_cc"` LeagueSportID int32 `json:"league_sport_id"` Events []domain.EventWithSettingsRes `json:"events"` // Total int64 `json:"total"` } // @Summary Retrieve all top leagues // @Description Retrieve all top leagues // @Tags prematch // @Accept json // @Produce json // @Success 200 {array} TopLeague // @Failure 500 {object} response.APIResponse // @Router /api/v1/{tenant_slug}/top-leagues [get] func (h *Handler) GetTopLeagues(c *fiber.Ctx) error { companyID := c.Locals("company_id").(domain.ValidInt64) if !companyID.Valid { h.BadRequestLogger().Error("invalid company id") return fiber.NewError(fiber.StatusBadRequest, "invalid company id") } leagues, _, err := h.leagueSvc.GetAllLeaguesByCompany(c.Context(), companyID.Value, domain.LeagueFilter{ IsFeatured: domain.ValidBool{ Value: true, Valid: true, }, }) if err != nil { h.InternalServerErrorLogger().Error("Error while fetching top leagues", zap.Int64("company_id", companyID.Value), zap.Error(err), ) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } var topLeague []TopLeague = make([]TopLeague, 0, len(leagues)) for _, league := range leagues { events, _, err := h.eventSvc.GetEventsWithSettings( c.Context(), companyID.Value, domain.EventFilter{ LeagueID: domain.ValidInt64{ Value: league.ID, Valid: true, }, Active: domain.ValidBool{Value: true, Valid: true}, }) if err != nil { h.InternalServerErrorLogger().Warn("Error while fetching events for top league", zap.Int64("LeagueID", league.ID), zap.Int64("company_id", companyID.Value), zap.Error(err), ) } topLeague = append(topLeague, TopLeague{ LeagueID: league.ID, LeagueName: league.Name, LeagueCC: league.CountryCode.Value, LeagueSportID: league.SportID, Events: domain.ConvertEventWithSettingResList(events), }) } res := TopLeaguesRes{ Leagues: topLeague, } return response.WriteJSON(c, fiber.StatusOK, "All top leagues events retrieved successfully", res, nil) } // @Summary Retrieve an upcoming by ID // @Description Retrieve an upcoming event by ID // @Tags prematch // @Accept json // @Produce json // @Param id path string true "ID" // @Success 200 {object} domain.BaseEvent // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /api/v1/events/{id} [get] func (h *Handler) GetEventByID(c *fiber.Ctx) error { idStr := c.Params("id") eventID, err := strconv.ParseInt(idStr, 10, 64) if err != nil { h.BadRequestLogger().Info("Failed to parse event id", zap.String("id", idStr)) return fiber.NewError(fiber.StatusBadRequest, "Missing id") } event, err := h.eventSvc.GetEventByID(c.Context(), eventID) if err != nil { h.InternalServerErrorLogger().Error("Failed to get event by id", zap.Int64("eventID", eventID), zap.Error(err), ) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } res := domain.ConvertEventRes(event) return response.WriteJSON(c, fiber.StatusOK, "Upcoming event retrieved successfully", res, nil) } // @Summary Retrieve an upcoming by ID // @Description Retrieve an upcoming event by ID // @Tags prematch // @Accept json // @Produce json // @Param id path string true "ID" // @Success 200 {object} domain.BaseEvent // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /api/v1/{tenant_slug}events/{id} [get] func (h *Handler) GetTenantEventByID(c *fiber.Ctx) error { companyID := c.Locals("company_id").(domain.ValidInt64) if !companyID.Valid { h.BadRequestLogger().Error("invalid company id") return fiber.NewError(fiber.StatusBadRequest, "invalid company id") } idStr := c.Params("id") eventID, err := strconv.ParseInt(idStr, 10, 64) if err != nil { h.BadRequestLogger().Info("Failed to parse event id", zap.String("id", idStr)) return fiber.NewError(fiber.StatusBadRequest, "Missing id") } event, err := h.eventSvc.GetEventWithSettingByID(c.Context(), eventID, companyID.Value) if err != nil { h.InternalServerErrorLogger().Error("Failed to get upcoming event by id", zap.Int64("eventID", eventID), zap.Error(err), ) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } res := domain.ConvertEventWitSettingRes(event) return response.WriteJSON(c, fiber.StatusOK, "Upcoming event retrieved successfully", res, nil) } // @Summary Retrieve bet outcomes by event id // @Description Retrieve bet outcomes by event id // @Tags prematch // @Accept json // @Produce json // @Param id path string true "ID" // @Success 200 {object} domain.BaseEvent // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /api/v1/tenant/{tenant_slug}/events/{id}/bets [get] func (h *Handler) GetTenantBetsByEventID(c *fiber.Ctx) error { companyID := c.Locals("company_id").(domain.ValidInt64) if !companyID.Valid { h.BadRequestLogger().Error("invalid company id") return fiber.NewError(fiber.StatusBadRequest, "invalid company id") } idStr := c.Params("id") eventID, err := strconv.ParseInt(idStr, 10, 64) if err != nil { h.BadRequestLogger().Info("Failed to parse event id", zap.String("id", idStr)) return fiber.NewError(fiber.StatusBadRequest, "Missing id") } page := c.QueryInt("page", 1) pageSize := c.QueryInt("page_size", 10) limit := domain.ValidInt32{ Value: int32(pageSize), Valid: true, } offset := domain.ValidInt32{ Value: int32(page - 1), Valid: true, } statusQuery := c.Params("status") var status domain.ValidOutcomeStatus if statusQuery != "" { statusIntParse, err := strconv.ParseInt(statusQuery, 10, 32) if err != nil { h.BadRequestLogger().Info("Failed to parse status", zap.String("status", statusQuery)) return fiber.NewError(fiber.StatusBadRequest, "Invalid status query") } statusParsed, err := domain.ParseOutcomeStatus(int(statusIntParse)) if err != nil { h.BadRequestLogger().Info("Failed to parse status", zap.String("status", statusQuery)) return fiber.NewError(fiber.StatusBadRequest, "Invalid status query") } status = domain.ValidOutcomeStatus{ Value: statusParsed, Valid: true, } } res, total, err := h.betSvc.GetBetOutcomeViewByEventID(c.Context(), eventID, domain.BetOutcomeViewFilter{ OutcomeStatus: status, CompanyID: companyID, Limit: limit, Offset: offset, }) if err != nil { h.InternalServerErrorLogger().Error("Failed to get upcoming event by id", zap.Int64("eventID", eventID), zap.Error(err), ) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } return response.WritePaginatedJSON(c, fiber.StatusOK, "Bet Outcomes retrieved successfully", res, nil, page, int(total)) } // @Summary Retrieve bet outcomes by event id // @Description Retrieve bet outcomes by event id // @Tags prematch // @Accept json // @Produce json // @Param id path string true "ID" // @Success 200 {object} domain.BaseEvent // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /api/v1/events/{id}/bets [get] func (h *Handler) GetBetsByEventID(c *fiber.Ctx) error { idStr := c.Params("id") eventID, err := strconv.ParseInt(idStr, 10, 64) if err != nil { h.BadRequestLogger().Info("Failed to parse event id", zap.String("id", idStr)) return fiber.NewError(fiber.StatusBadRequest, "Missing id") } page := c.QueryInt("page", 1) pageSize := c.QueryInt("page_size", 10) limit := domain.ValidInt32{ Value: int32(pageSize), Valid: true, } offset := domain.ValidInt32{ Value: int32(page - 1), Valid: true, } statusQuery := c.Params("status") var status domain.ValidOutcomeStatus if statusQuery != "" { statusIntParse, err := strconv.ParseInt(statusQuery, 10, 32) if err != nil { h.BadRequestLogger().Info("Failed to parse status", zap.String("status", statusQuery)) return fiber.NewError(fiber.StatusBadRequest, "Invalid status query") } statusParsed, err := domain.ParseOutcomeStatus(int(statusIntParse)) if err != nil { h.BadRequestLogger().Info("Failed to parse status", zap.String("status", statusQuery)) return fiber.NewError(fiber.StatusBadRequest, "Invalid status query") } status = domain.ValidOutcomeStatus{ Value: statusParsed, Valid: true, } } res, total, err := h.betSvc.GetBetOutcomeViewByEventID(c.Context(), eventID, domain.BetOutcomeViewFilter{ OutcomeStatus: status, Limit: limit, Offset: offset, }) if err != nil { h.InternalServerErrorLogger().Error("Failed to get upcoming event by id", zap.Int64("eventID", eventID), zap.Error(err), ) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } return response.WritePaginatedJSON(c, fiber.StatusOK, "Bet Outcomes retrieved successfully", res, nil, page, int(total)) } type UpdateEventStatusReq struct { } // SetEventStatusToRemoved godoc // @Summary Set the event status to removed // @Description Set the event status to removed // @Tags event // @Accept json // @Produce json // @Param id path int true "Event ID" // @Success 200 {object} response.APIResponse // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /api/v1/events/{id} [delete] func (h *Handler) SetEventStatusToRemoved(c *fiber.Ctx) error { idStr := c.Params("id") eventID, err := strconv.ParseInt(idStr, 10, 64) if err != nil { h.BadRequestLogger().Info("Failed to parse event id", zap.String("id", idStr)) return fiber.NewError(fiber.StatusBadRequest, "Missing id") } err = h.eventSvc.UpdateEventStatus(c.Context(), eventID, domain.STATUS_REMOVED) if err != nil { h.InternalServerErrorLogger().Error("Failed to update event status", zap.Int64("EventID", eventID), zap.Error(err), ) return fiber.NewError(fiber.StatusInternalServerError, "Failed to update event status") } return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil) } type UpdateEventSettingsReq struct { Featured *bool `json:"is_featured" example:"true"` IsActive *bool `json:"is_active" example:"true"` WinningUpperLimit *int64 `json:"winning_upper_limit" example:"10000"` } // UpdateEventSettings godoc // @Summary update the event settings // @Description Update the event settings // @Tags event // @Accept json // @Produce json // @Param id path int true "Event ID" // @Success 200 {object} response.APIResponse // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /api/v1/events/{id}/settings [put] func (h *Handler) UpdateEventSettings(c *fiber.Ctx) error { eventIDStr := c.Params("id") eventID, err := strconv.ParseInt(eventIDStr, 10, 64) if err != nil { h.BadRequestLogger().Error("invalid event id") return fiber.NewError(fiber.StatusBadRequest, "invalid event id") } var req UpdateEventSettingsReq if err := c.BodyParser(&req); err != nil { h.BadRequestLogger().Info("Failed to parse event id", zap.Int64("eventID", eventID), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, err.Error()) } logFields := []zap.Field{ zap.Int64("eventID", eventID), zap.Any("is_featured", req.Featured), zap.Any("is_active", req.IsActive), zap.Any("winning_upper_limit", req.WinningUpperLimit), } valErrs, ok := h.validator.Validate(c, req) if !ok { var errMsg string for field, msg := range valErrs { errMsg += fmt.Sprintf("%s: %s; ", field, msg) } h.BadRequestLogger().Error("Failed to update event settings", append(logFields, zap.String("errMsg", errMsg))..., ) return fiber.NewError(fiber.StatusBadRequest, errMsg) } err = h.eventSvc.UpdateGlobalEventSettings(c.Context(), domain.UpdateGlobalEventSettings{ EventID: eventID, IsFeatured: domain.ConvertBoolPtr(req.Featured), IsActive: domain.ConvertBoolPtr(req.IsActive), WinningUpperLimit: domain.ConvertInt64Ptr(req.WinningUpperLimit), }) if err != nil { h.InternalServerErrorLogger().Error("Failed to update event settings", append(logFields, zap.Error(err))...) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil) } // UpdateTenantEventSettings godoc // @Summary update the event settings // @Description Update the event settings // @Tags event // @Accept json // @Produce json // @Param id path int true "Event ID" // @Success 200 {object} response.APIResponse // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /api/v1/tenant/{tenant_slug}/events/{id}/settings [put] func (h *Handler) UpdateTenantEventSettings(c *fiber.Ctx) error { companyID := c.Locals("company_id").(domain.ValidInt64) if !companyID.Valid { h.BadRequestLogger().Error("invalid company id") return fiber.NewError(fiber.StatusBadRequest, "invalid company id") } eventIDStr := c.Params("id") eventID, err := strconv.ParseInt(eventIDStr, 10, 64) if err != nil { h.BadRequestLogger().Error("invalid event id") return fiber.NewError(fiber.StatusBadRequest, "invalid event id") } var req UpdateEventSettingsReq if err := c.BodyParser(&req); err != nil { h.BadRequestLogger().Info("Failed to parse event id", zap.Int64("eventID", eventID), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, err.Error()) } logFields := []zap.Field{ zap.Int64("eventID", eventID), zap.Int64("companyID", companyID.Value), zap.Any("is_featured", req.Featured), zap.Any("is_active", req.IsActive), zap.Any("winning_upper_limit", req.WinningUpperLimit), } valErrs, ok := h.validator.Validate(c, req) if !ok { var errMsg string for field, msg := range valErrs { errMsg += fmt.Sprintf("%s: %s; ", field, msg) } h.BadRequestLogger().Error("Failed to update event settings", append(logFields, zap.String("errMsg", errMsg))..., ) return fiber.NewError(fiber.StatusBadRequest, errMsg) } err = h.eventSvc.UpdateTenantEventSettings(c.Context(), domain.UpdateTenantEventSettings{ CompanyID: companyID.Value, EventID: eventID, IsFeatured: domain.ConvertBoolPtr(req.Featured), IsActive: domain.ConvertBoolPtr(req.IsActive), WinningUpperLimit: domain.ConvertInt64Ptr(req.WinningUpperLimit), }) if err != nil { h.InternalServerErrorLogger().Error("Failed to update event settings", append(logFields, zap.Error(err))...) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil) } type SetEventIsMonitoredReq struct { IsMonitored bool `json:"is_monitored"` } // SetEventIsMonitored godoc // @Summary update the event is_monitored // @Description Update the event is_monitored // @Tags event // @Accept json // @Produce json // @Param id path int true "Event ID" // @Success 200 {object} response.APIResponse // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /api/v1/events/{id}/is_monitored [patch] func (h *Handler) SetEventIsMonitored(c *fiber.Ctx) error { idStr := c.Params("id") eventID, err := strconv.ParseInt(idStr, 10, 64) if err != nil { h.BadRequestLogger().Info("Failed to parse event id", zap.String("id", idStr)) return fiber.NewError(fiber.StatusBadRequest, "Missing id") } var req SetEventIsMonitoredReq if err := c.BodyParser(&req); err != nil { h.BadRequestLogger().Info("Failed to parse bet id", zap.Int64("eventID", eventID), zap.Error(err), ) return fiber.NewError(fiber.StatusBadRequest, err.Error()) } logFields := []zap.Field{ zap.Int64("eventID", eventID), zap.Any("is_featured", req.IsMonitored), } valErrs, ok := h.validator.Validate(c, req) if !ok { var errMsg string for field, msg := range valErrs { errMsg += fmt.Sprintf("%s: %s; ", field, msg) } h.BadRequestLogger().Error("Failed to update event featured", append(logFields, zap.String("errMsg", errMsg))..., ) return fiber.NewError(fiber.StatusBadRequest, errMsg) } err = h.eventSvc.UpdateEventMonitored(c.Context(), eventID, req.IsMonitored) if err != nil { h.InternalServerErrorLogger().Error("Failed to update event is_monitored", append(logFields, zap.Error(err))...) return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil) }