Yimaru-BackEnd/internal/web_server/handlers/prematch.go
2025-06-25 14:24:40 +03:00

323 lines
10 KiB
Go

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"
)
// GetALLPrematchOdds
// @Summary Retrieve all prematch odds
// @Description Retrieve all prematch odds from the database
// @Tags prematch
// @Accept json
// @Produce json
// @Success 200 {array} domain.Odd
// @Failure 500 {object} response.APIResponse
// @Router /odds [get]
func (h *Handler) GetALLPrematchOdds(c *fiber.Ctx) error {
odds, err := h.prematchSvc.GetALLPrematchOdds(c.Context())
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all prematch odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "All prematch odds retrieved successfully", odds, nil)
}
// GetRawOddsByMarketID
// @Summary Retrieve raw odds by Market ID
// @Description Retrieve raw odds records using a Market ID
// @Tags prematch
// @Accept json
// @Produce json
// @Param upcoming_id path string true "Upcoming ID"
// @Param market_id path string true "Market ID"
// @Success 200 {array} domain.RawOddsByMarketID
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /odds/upcoming/{upcoming_id}/market/{market_id} [get]
func (h *Handler) GetRawOddsByMarketID(c *fiber.Ctx) error {
marketID := c.Params("market_id")
upcomingID := c.Params("upcoming_id")
if marketID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing market_id", nil, nil)
}
if upcomingID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
}
rawOdds, err := h.prematchSvc.GetRawOddsByMarketID(c.Context(), marketID, upcomingID)
if err != nil {
// fmt.Printf("Failed to fetch raw odds: %v market_id:%v upcomingID:%v\n", err, marketID, upcomingID)
h.logger.Error("Failed to get raw odds by market ID", "marketID", marketID, "upcomingID", upcomingID, "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve raw odds", err, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Raw odds retrieved successfully", rawOdds, 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.UpcomingEvent
// @Failure 500 {object} response.APIResponse
// @Router /events [get]
func (h *Handler) GetAllUpcomingEvents(c *fiber.Ctx) error {
page := c.QueryInt("page", 1)
pageSize := c.QueryInt("page_size", 10)
limit := domain.ValidInt64{
Value: int64(pageSize),
Valid: true,
}
offset := domain.ValidInt64{
Value: int64(page - 1),
Valid: true,
}
leagueIDQuery := c.Query("league_id")
var leagueID domain.ValidInt32
if leagueIDQuery != "" {
leagueIDInt, err := strconv.Atoi(leagueIDQuery)
if err != nil {
h.logger.Error("invalid league id", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid league id", nil, nil)
}
leagueID = domain.ValidInt32{
Value: int32(leagueIDInt),
Valid: true,
}
}
sportIDQuery := c.Query("sport_id")
var sportID domain.ValidInt32
if sportIDQuery != "" {
sportIDint, err := strconv.Atoi(sportIDQuery)
if err != nil {
h.logger.Error("invalid sport id", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "invalid sport id", nil, nil)
}
sportID = domain.ValidInt32{
Value: int32(sportIDint),
Valid: true,
}
}
firstStartTimeQuery := c.Query("first_start_time")
var firstStartTime domain.ValidTime
if firstStartTimeQuery != "" {
firstStartTimeParsed, err := time.Parse(time.RFC3339, firstStartTimeQuery)
if err != nil {
h.logger.Error("invalid start_time format", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
}
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.logger.Error("invalid start_time format", "error", err)
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil)
}
lastStartTime = domain.ValidTime{
Value: lastStartTimeParsed,
Valid: true,
}
}
countryCodeQuery := c.Query("cc")
countryCode := domain.ValidString{
Value: countryCodeQuery,
Valid: countryCodeQuery != "",
}
events, total, err := h.eventSvc.GetPaginatedUpcomingEvents(
c.Context(), domain.EventFilter{
SportID: sportID,
LeagueID: leagueID,
FirstStartTime: firstStartTime,
LastStartTime: lastStartTime,
Limit: limit,
Offset: offset,
CountryCode: countryCode,
})
// fmt.Printf("League ID: %v", leagueID)
if err != nil {
h.logger.Error("getting error", "error", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve all upcoming events", nil, nil)
}
return response.WritePaginatedJSON(c, fiber.StatusOK, "All upcoming events retrieved successfully", events, 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.UpcomingEvent `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 /top-leagues [get]
func (h *Handler) GetTopLeagues(c *fiber.Ctx) error {
leagues, err := h.leagueSvc.GetFeaturedLeagues(c.Context())
if err != nil {
h.logger.Error("Error while fetching top leagues", "err", err)
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get featured leagues", nil, nil)
}
var topLeague []TopLeague = make([]TopLeague, 0, len(leagues))
for _, league := range leagues {
events, _, err := h.eventSvc.GetPaginatedUpcomingEvents(
c.Context(), domain.EventFilter{
LeagueID: domain.ValidInt32{
Value: int32(league.ID),
Valid: true,
},
})
if err != nil {
fmt.Printf("Error while fetching events for top league %v \n", league.ID)
h.logger.Error("Error while fetching events for top league", "League ID", league.ID)
}
topLeague = append(topLeague, TopLeague{
LeagueID: league.ID,
LeagueName: league.Name,
LeagueCC: league.CountryCode,
LeagueSportID: league.SportID,
Events: 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.UpcomingEvent
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /events/{id} [get]
func (h *Handler) GetUpcomingEventByID(c *fiber.Ctx) error {
id := c.Params("id")
if id == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing id", nil, nil)
}
event, err := h.eventSvc.GetUpcomingEventByID(c.Context(), id)
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve upcoming event", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Upcoming event retrieved successfully", event, nil)
}
// @Summary Retrieve prematch odds by upcoming ID (FI)
// @Description Retrieve prematch odds by upcoming event ID (FI from Bet365) with optional pagination
// @Tags prematch
// @Accept json
// @Produce json
// @Param upcoming_id path string true "Upcoming Event ID (FI)"
// @Param limit query int false "Number of results to return (default: 10)"
// @Param offset query int false "Number of results to skip (default: 0)"
// @Success 200 {array} domain.Odd
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /odds/upcoming/{upcoming_id} [get]
func (h *Handler) GetOddsByUpcomingID(c *fiber.Ctx) error {
upcomingID := c.Params("upcoming_id")
if upcomingID == "" {
return response.WriteJSON(c, fiber.StatusBadRequest, "Missing upcoming_id", nil, nil)
}
limit, err := strconv.Atoi(c.Query("limit", "10")) // Default limit is 10
if err != nil || limit <= 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid limit value", nil, nil)
}
offset, err := strconv.Atoi(c.Query("offset", "0")) // Default offset is 0
if err != nil || offset < 0 {
return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid offset value", nil, nil)
}
odds, err := h.prematchSvc.GetPrematchOddsByUpcomingID(c.Context(), upcomingID)
if err != nil {
return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve prematch odds", nil, nil)
}
return response.WriteJSON(c, fiber.StatusOK, "Prematch odds retrieved successfully", odds, nil)
}
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 /events/{id} [delete]
func (h *Handler) SetEventStatusToRemoved(c *fiber.Ctx) error {
eventID := c.Params("id")
err := h.eventSvc.UpdateEventStatus(c.Context(), eventID, domain.STATUS_REMOVED)
if err != nil {
h.logger.Error("Failed to update event status", "eventID", eventID, "error", err)
}
return response.WriteJSON(c, fiber.StatusOK, "Event updated successfully", nil, nil)
}