package controllers import ( "strconv" "abdanhafidz.com/go-boilerplate/services" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type AdminStatisticController interface { GetSummary(ctx *gin.Context) GetMonthlyGrowth(ctx *gin.Context) GetEventOverview(ctx *gin.Context) GetEventDetail(ctx *gin.Context) GetExamOverview(ctx *gin.Context) GetExamDetail(ctx *gin.Context) GetAcademyOverview(ctx *gin.Context) GetAcademyDetail(ctx *gin.Context) GetProblemSetOverview(ctx *gin.Context) GetProblemSetDetail(ctx *gin.Context) GetQuestionOverview(ctx *gin.Context) GetQuestionDetail(ctx *gin.Context) } type adminStatisticController struct { adminStatisticService services.AdminStatisticService } func NewAdminStatisticController(adminStatisticService services.AdminStatisticService) AdminStatisticController { return &adminStatisticController{adminStatisticService: adminStatisticService} } // GetSummary godoc // @Summary Admin: Get Statistics Summary // @Description Retrieve aggregate statistics for dashboard cards such as users, academies, events, exams, problemsets, attempts, and payment metrics // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Success 200 {object} dto.AdminStatisticSummaryResponse // @Failure 401 {object} dto.ErrorResponse // @Failure 403 {object} dto.ErrorResponse // @Failure 500 {object} dto.ErrorResponse // @Router /api/v1/admin/statistics/summary [get] func (c *adminStatisticController) GetSummary(ctx *gin.Context) { summary, err := c.adminStatisticService.GetSummary(ctx.Request.Context()) ResponseJSON(ctx, gin.H{}, summary, err) } // GetMonthlyGrowth godoc // @Summary Admin: Get Monthly Growth Statistics // @Description Retrieve monthly growth trend for users, academies, events, exams, and problemsets // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Param months query int false "How many months to include" default(6) // @Success 200 {object} dto.AdminStatisticMonthlyGrowthResponse // @Failure 401 {object} dto.ErrorResponse // @Failure 403 {object} dto.ErrorResponse // @Failure 500 {object} dto.ErrorResponse // @Router /api/v1/admin/statistics/monthly-growth [get] func (c *adminStatisticController) GetMonthlyGrowth(ctx *gin.Context) { months, _ := strconv.Atoi(ctx.DefaultQuery("months", "6")) if months < 1 { months = 6 } if months > 24 { months = 24 } result, err := c.adminStatisticService.GetMonthlyGrowth(ctx.Request.Context(), months) meta := gin.H{"months": months} ResponseJSON(ctx, meta, result, err) } // GetEventOverview godoc // @Summary Admin: Get Event Statistics Overview // @Description Aggregate statistics for all events // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Router /api/v1/admin/statistics/event [get] func (c *adminStatisticController) GetEventOverview(ctx *gin.Context) { result, err := c.adminStatisticService.GetEventOverview(ctx.Request.Context()) ResponseJSON(ctx, gin.H{}, result, err) } // GetEventDetail godoc // @Summary Admin: Get Event Statistics Detail // @Description Aggregate statistics for a single event // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Param event_id path string true "Event ID" // @Router /api/v1/admin/statistics/event/{event_id} [get] func (c *adminStatisticController) GetEventDetail(ctx *gin.Context) { eventID := ParseUUID(ctx, "event_id") if eventID == uuid.Nil { return } result, err := c.adminStatisticService.GetEventDetail(ctx.Request.Context(), eventID) ResponseJSON(ctx, gin.H{"event_id": eventID}, result, err) } // GetExamOverview godoc // @Summary Admin: Get Exam Statistics Overview // @Description Aggregate statistics for all exams // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Router /api/v1/admin/statistics/exam [get] func (c *adminStatisticController) GetExamOverview(ctx *gin.Context) { result, err := c.adminStatisticService.GetExamOverview(ctx.Request.Context()) ResponseJSON(ctx, gin.H{}, result, err) } // GetExamDetail godoc // @Summary Admin: Get Exam Statistics Detail // @Description Aggregate statistics for a single exam // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Param exam_id path string true "Exam ID" // @Router /api/v1/admin/statistics/exam/{exam_id} [get] func (c *adminStatisticController) GetExamDetail(ctx *gin.Context) { examID := ParseUUID(ctx, "exam_id") if examID == uuid.Nil { return } result, err := c.adminStatisticService.GetExamDetail(ctx.Request.Context(), examID) ResponseJSON(ctx, gin.H{"exam_id": examID}, result, err) } // GetAcademyOverview godoc // @Summary Admin: Get Academy Statistics Overview // @Description Aggregate statistics for all academies // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Router /api/v1/admin/statistics/academy [get] func (c *adminStatisticController) GetAcademyOverview(ctx *gin.Context) { result, err := c.adminStatisticService.GetAcademyOverview(ctx.Request.Context()) ResponseJSON(ctx, gin.H{}, result, err) } // GetAcademyDetail godoc // @Summary Admin: Get Academy Statistics Detail // @Description Aggregate statistics for a single academy // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Param academy_id path string true "Academy ID" // @Router /api/v1/admin/statistics/academy/{academy_id} [get] func (c *adminStatisticController) GetAcademyDetail(ctx *gin.Context) { academyID := ParseUUID(ctx, "academy_id") if academyID == uuid.Nil { return } result, err := c.adminStatisticService.GetAcademyDetail(ctx.Request.Context(), academyID) ResponseJSON(ctx, gin.H{"academy_id": academyID}, result, err) } // GetProblemSetOverview godoc // @Summary Admin: Get ProblemSet Statistics Overview // @Description Aggregate statistics for all problemsets // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Router /api/v1/admin/statistics/problemset [get] func (c *adminStatisticController) GetProblemSetOverview(ctx *gin.Context) { result, err := c.adminStatisticService.GetProblemSetOverview(ctx.Request.Context()) ResponseJSON(ctx, gin.H{}, result, err) } // GetProblemSetDetail godoc // @Summary Admin: Get ProblemSet Statistics Detail // @Description Aggregate statistics for a single problemset // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Param problemset_id path string true "ProblemSet ID" // @Router /api/v1/admin/statistics/problemset/{problemset_id} [get] func (c *adminStatisticController) GetProblemSetDetail(ctx *gin.Context) { problemSetID := ParseUUID(ctx, "problemset_id") if problemSetID == uuid.Nil { return } result, err := c.adminStatisticService.GetProblemSetDetail(ctx.Request.Context(), problemSetID) ResponseJSON(ctx, gin.H{"problemset_id": problemSetID}, result, err) } // GetQuestionOverview godoc // @Summary Admin: Get Question Statistics Overview // @Description Aggregate statistics for all questions // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Router /api/v1/admin/statistics/question [get] func (c *adminStatisticController) GetQuestionOverview(ctx *gin.Context) { result, err := c.adminStatisticService.GetQuestionOverview(ctx.Request.Context()) ResponseJSON(ctx, gin.H{}, result, err) } // GetQuestionDetail godoc // @Summary Admin: Get Question Statistics Detail // @Description Aggregate statistics for a single question // @Tags AdminStatistic // @Accept json // @Produce json // @Security BearerAuth // @Param question_id path string true "Question ID" // @Router /api/v1/admin/statistics/question/{question_id} [get] func (c *adminStatisticController) GetQuestionDetail(ctx *gin.Context) { questionID := ParseUUID(ctx, "question_id") if questionID == uuid.Nil { return } result, err := c.adminStatisticService.GetQuestionDetail(ctx.Request.Context(), questionID) ResponseJSON(ctx, gin.H{"question_id": questionID}, result, err) }