package handlers import ( "log/slog" "strconv" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/ticket" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator" "github.com/gofiber/fiber/v2" ) type TicketOutcome struct { EventID int64 `json:"event_id" example:"1"` OddID int64 `json:"odd_id" example:"1"` } type CreateTicketReq struct { Outcomes []TicketOutcome `json:"outcomes"` Amount float32 `json:"amount" example:"100.0"` TotalOdds float32 `json:"total_odds" example:"4.22"` } type CreateTicketRes struct { FastCode int64 `json:"fast_code" example:"1234"` CreatedNumber int64 `json:"created_number" example:"3"` } // CreateTicket godoc // @Summary Create a temporary ticket // @Description Creates a temporary ticket // @Tags ticket // @Accept json // @Produce json // @Param createTicket body CreateTicketReq true "Creates ticket" // @Success 200 {object} CreateTicketRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /ticket [post] func CreateTicket(logger *slog.Logger, ticketSvc *ticket.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { var req CreateTicketReq if err := c.BodyParser(&req); err != nil { logger.Error("CreateTicketReq failed", "error", err) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "Invalid request", }) } valErrs, ok := validator.Validate(c, req) if !ok { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } // TODO Validate Outcomes Here and make sure they didn't expire ticket, err := ticketSvc.CreateTicket(c.Context(), domain.CreateTicket{ Amount: domain.Currency(req.Amount), TotalOdds: req.TotalOdds, }) if err != nil { logger.Error("CreateTicketReq failed", "error", err) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Internal server error", }) } var outcomes []domain.CreateTicketOutcome = make([]domain.CreateTicketOutcome, 0, len(req.Outcomes)) for _, outcome := range req.Outcomes { outcomes = append(outcomes, domain.CreateTicketOutcome{ TicketID: ticket.ID, EventID: outcome.EventID, OddID: outcome.OddID, }) } rows, err := ticketSvc.CreateTicketOutcome(c.Context(), outcomes) if err != nil { logger.Error("CreateTicketReq failed to create outcomes", "error", err) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Internal server error", }) } res := CreateTicketRes{ FastCode: ticket.ID, CreatedNumber: rows, } return response.WriteJSON(c, fiber.StatusOK, "Ticket Created", res, nil) } } type TicketRes struct { ID int64 `json:"id" example:"1"` Outcomes []domain.TicketOutcome `json:"outcomes"` Amount float32 `json:"amount" example:"100.0"` TotalOdds float32 `json:"total_odds" example:"4.22"` } // GetTicketByID godoc // @Summary Get ticket by ID // @Description Retrieve ticket details by ticket ID // @Tags ticket // @Accept json // @Produce json // @Param id path int true "Ticket ID" // @Success 200 {object} TicketRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /ticket/{id} [get] func GetTicketByID(logger *slog.Logger, ticketSvc *ticket.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { ticketID := c.Params("id") id, err := strconv.ParseInt(ticketID, 10, 64) if err != nil { logger.Error("Invalid ticket ID", "ticketID", ticketID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid ticket ID", err, nil) } ticket, err := ticketSvc.GetTicketByID(c.Context(), id) if err != nil { logger.Error("Failed to get ticket by ID", "ticketID", id, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve ticket", err, nil) } res := TicketRes{ ID: ticket.ID, Outcomes: ticket.Outcomes, Amount: ticket.Amount.Float64(), TotalOdds: ticket.TotalOdds, } return response.WriteJSON(c, fiber.StatusOK, "Ticket retrieved successfully", res, nil) } } // GetAllTickets godoc // @Summary Get all tickets // @Description Retrieve all tickets // @Tags ticket // @Accept json // @Produce json // @Success 200 {array} TicketRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /ticket [get] func GetAllTickets(logger *slog.Logger, ticketSvc *ticket.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { tickets, err := ticketSvc.GetAllTickets(c.Context()) if err != nil { logger.Error("Failed to get tickets", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve tickets", err, nil) } var res []TicketRes = make([]TicketRes, 0, len(tickets)) for _, ticket := range tickets { res = append(res, TicketRes{ ID: ticket.ID, Outcomes: ticket.Outcomes, Amount: ticket.Amount.Float64(), TotalOdds: ticket.TotalOdds, }) } return response.WriteJSON(c, fiber.StatusOK, "All Tickets retrieved", res, nil) } }