package handlers import ( "log" "sno/internal/middleware" "sno/internal/models" "sno/internal/service" "strconv" "github.com/gofiber/fiber/v2" ) // RewardHandler handles HTTP requests for rewards. type RewardHandler struct { rewardService service.RewardService } // NewRewardHandler creates a new instance of a reward handler. func NewRewardHandler(s service.RewardService) *RewardHandler { return &RewardHandler{rewardService: s} } // CreateReward handles the request to create a new reward. // @Summary Create a new reward // @Description Creates a new reward that users can purchase with stars (admin/operator only) // @Tags rewards // @Accept json // @Produce json // @Param reward body models.Reward true "Reward object" // @Success 201 {object} object{success=bool,message=string,data=models.Reward} // @Failure 400 {object} object{success=bool,message=string} // @Failure 500 {object} object{success=bool,message=string} // @Router /api/admin/rewards [post] // @Security ApiKeyAuth func (h *RewardHandler) CreateReward(c *fiber.Ctx) error { var reward models.Reward if err := c.BodyParser(&reward); err != nil { return c.Status(fiber.StatusBadRequest).JSON(Response{ Success: false, Message: "Cannot parse JSON", }) } // TODO: Get CreatedBy from admin auth middleware createdReward, err := h.rewardService.CreateReward(c.Context(), &reward) if err != nil { log.Printf("ERROR: Failed to create reward: %v", err) return c.Status(fiber.StatusInternalServerError).JSON(Response{ Success: false, Message: err.Error(), }) } return c.Status(fiber.StatusCreated).JSON(Response{ Success: true, Message: "Reward created successfully", Data: createdReward, }) } // GetAllRewards handles the request to get all active rewards. // @Summary Get all active rewards // @Description Returns a list of all active rewards available for purchase // @Tags rewards // @Accept json // @Produce json // @Success 200 {object} object{success=bool,message=string,data=[]models.Reward} // @Failure 500 {object} object{success=bool,message=string} // @Router /api/rewards [get] // @Security ApiKeyAuth func (h *RewardHandler) GetAllRewards(c *fiber.Ctx) error { rewards, err := h.rewardService.ListActiveRewards(c.Context()) if err != nil { log.Printf("ERROR: Failed to list rewards: %v", err) return c.Status(fiber.StatusInternalServerError).JSON(Response{ Success: false, Message: "Failed to retrieve rewards", }) } return c.Status(fiber.StatusOK).JSON(Response{ Success: true, Message: "Rewards retrieved successfully", Data: rewards, }) } // PurchaseReward handles the request for a user to purchase a reward. // @Summary Purchase a reward // @Description Allows a user to purchase a reward using their stars // @Tags rewards // @Accept json // @Produce json // @Param id path int true "Reward ID" // @Success 200 {object} object{success=bool,message=string,data=models.Purchase} // @Failure 400 {object} object{success=bool,message=string} // @Failure 500 {object} object{success=bool,message=string} // @Router /api/rewards/{id}/purchase [post] // @Security ApiKeyAuth func (h *RewardHandler) PurchaseReward(c *fiber.Ctx) error { rewardID, err := strconv.Atoi(c.Params("id")) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(Response{ Success: false, Message: "Invalid reward ID", }) } // Get user data from auth middleware userData := middleware.GetTelegramUser(c) if userData == nil { return c.Status(fiber.StatusUnauthorized).JSON(Response{ Success: false, Message: "User not authenticated", }) } purchase, err := h.rewardService.PurchaseReward(c.Context(), userData.ID, rewardID) if err != nil { log.Printf("ERROR: Failed to purchase reward: %v", err) // Potentially return different status codes based on error type return c.Status(fiber.StatusInternalServerError).JSON(Response{ Success: false, Message: err.Error(), }) } return c.Status(fiber.StatusOK).JSON(Response{ Success: true, Message: "Reward purchased successfully", Data: purchase, }) } // UpdateReward handles the request to update an existing reward. // @Summary Update a reward // @Description Updates an existing reward (admin only) // @Tags rewards // @Accept json // @Produce json // @Param id path int true "Reward ID" // @Param reward body models.Reward true "Updated reward object" // @Success 200 {object} object{success=bool,message=string,data=models.Reward} // @Failure 400 {object} object{success=bool,message=string} // @Failure 500 {object} object{success=bool,message=string} // @Router /api/admin/rewards/{id} [put] // @Security ApiKeyAuth func (h *RewardHandler) UpdateReward(c *fiber.Ctx) error { id, err := strconv.Atoi(c.Params("id")) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(Response{ Success: false, Message: "Invalid reward ID", }) } var reward models.Reward if err := c.BodyParser(&reward); err != nil { return c.Status(fiber.StatusBadRequest).JSON(Response{ Success: false, Message: "Cannot parse JSON", }) } updatedReward, err := h.rewardService.UpdateReward(c.Context(), id, &reward) if err != nil { log.Printf("ERROR: Failed to update reward: %v", err) return c.Status(fiber.StatusInternalServerError).JSON(Response{ Success: false, Message: err.Error(), }) } return c.Status(fiber.StatusOK).JSON(Response{ Success: true, Message: "Reward updated successfully", Data: updatedReward, }) } // DeleteReward handles the request to delete a reward. // @Summary Delete a reward // @Description Deletes a reward (admin only) // @Tags rewards // @Accept json // @Produce json // @Param id path int true "Reward ID" // @Success 200 {object} object{success=bool,message=string} // @Failure 400 {object} object{success=bool,message=string} // @Failure 500 {object} object{success=bool,message=string} // @Router /api/admin/rewards/{id} [delete] // @Security ApiKeyAuth func (h *RewardHandler) DeleteReward(c *fiber.Ctx) error { id, err := strconv.Atoi(c.Params("id")) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(Response{ Success: false, Message: "Invalid reward ID", }) } err = h.rewardService.DeleteReward(c.Context(), id) if err != nil { log.Printf("ERROR: Failed to delete reward: %v", err) return c.Status(fiber.StatusInternalServerError).JSON(Response{ Success: false, Message: err.Error(), }) } return c.Status(fiber.StatusOK).JSON(Response{ Success: true, Message: "Reward deleted successfully", }) }