package monitoring

import (
	"net/http"

	"github.com/tidbcloud/devops/api"
	monapi "github.com/tidbcloud/devops/api/monitoring"
	monent "github.com/tidbcloud/devops/entity/monitoring"
	ctrl "github.com/tidbcloud/devops/pkg/controller"
	monsvc "github.com/tidbcloud/devops/pkg/service/monitoring"

	"github.com/gin-gonic/gin"
	"go.uber.org/dig"
)

type ControllerParam struct {
	dig.In

	Monitoring monsvc.MonitoringServiceAPI
}

type MonitoringController struct {
	svc monsvc.MonitoringServiceAPI
}

func (c *MonitoringController) Name() string {
	return "MonitoringController"
}

func NewMonitoringController(p ControllerParam) ctrl.Controller {
	return &MonitoringController{
		svc: p.Monitoring,
	}
}

func (c *MonitoringController) RegisterAPI(suite *ctrl.Suite) error {
	r := suite.Router
	group := r.Group("/monitoring")
	{
		group.GET("/certificate/regions/:region", c.ListClusterCertificates)

		group.POST("/component-diff/reports", c.CreateComponentDiffReport)
		group.GET("/component-diff/reports/:type", c.ListComponentDiffReports)
		group.GET("/component-diff/reports/:type/:name", c.GetComponentDiffReport)

		group.POST("/weekly-idle-report/report-week", c.NotifyWeeklyIdleReport)
		group.POST("/weekly-idle-report/report-jira", c.NotifyJiraReport)
	}

	internalRouter := suite.InternalRouter
	iGroup := internalRouter.Group("/certificate")
	{
		iGroup.POST("/check", c.CheckCertificate)
	}
	return nil
}

func (c *MonitoringController) ListClusterCertificates(ctx *gin.Context) {
	region := ctx.Param("region")

	certificates, err := c.svc.ListClusterCertificates(ctx, region)
	if err != nil {
		ctx.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	ctx.JSON(http.StatusOK, certificates)
}

func (c *MonitoringController) CheckCertificate(ctx *gin.Context) {
	err := c.svc.CheckCertificate(ctx)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	ctrl.Success(ctx, api.EmptyResp{})
}

// PostComponentDiffReport
//
//	@Id				MonitoringControllerPostComponentDiffReport
//	@Description	generate component diff reports
//	@Tags			MonitoringController
//	@Accept			json
//	@Produce		json
//	@Success		200		{object}	api.BaseResp
//	@Failure		default	{object}	api.BaseResp
//	@Router			/api/v1/devops/monitoring/component-diff/reports [post]
func (c *MonitoringController) CreateComponentDiffReport(ctx *gin.Context) {
	err := c.svc.CheckComponentDiff(ctx)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	ctrl.Success(ctx, nil)
}

// ListComponentDiffReports
//
//	@Id				MonitoringControllerListComponentDiffReports
//	@Description	list component diff reports
//	@Tags			MonitoringController
//	@Accept			json
//	@Produce		json
//	@Param			type	path		string	true	"type"
//	@Success		200		{object}	monapi.ListReportsResponse
//	@Failure		default	{object}	api.BaseResp
//	@Router			/api/v1/devops/monitoring/component-diff/reports/{type} [get]
func (c *MonitoringController) ListComponentDiffReports(ctx *gin.Context) {
	typ := monent.ComponentDifferenceReportType(ctx.Param("type"))

	metadatas, err := c.svc.ListComponentDiffReports(ctx, typ)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	resp := &monapi.ListReportsResponse{
		Metadatas: metadatas,
	}
	ctrl.Success(ctx, resp)
}

// GetComponentDiffReport
//
//	@Id				MonitoringControllerGetComponentDiffReport
//	@Description	get component diff report by name
//	@Tags			MonitoringController
//	@Accept			json
//	@Produce		json
//	@Param			type	path		string	true	"type"
//	@Param			name	path		string	true	"name"
//	@Success		200		{object}	monapi.GetReportResponse
//	@Failure		default	{object}	api.BaseResp
//	@Router			/api/v1/devops/monitoring/component-diff/reports/{type}/{name} [get]
func (c *MonitoringController) GetComponentDiffReport(ctx *gin.Context) {
	typ := monent.ComponentDifferenceReportType(ctx.Param("type"))
	name := ctx.Param("name")

	metadata, report, err := c.svc.GetComponentDiffReport(ctx, typ, name)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	resp := &monapi.GetReportResponse{
		Metadata: *metadata,
		Report:   *report,
	}
	ctrl.Success(ctx, resp)
}

func (c *MonitoringController) NotifyWeeklyIdleReport(ctx *gin.Context) {
	err := c.svc.NotifyWeeklyIdleReport(ctx)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}
	ctrl.Success(ctx, nil)
}

func (c *MonitoringController) NotifyJiraReport(ctx *gin.Context) {
	err := c.svc.NotifyJiraReport(ctx)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}
	ctrl.Success(ctx, nil)
}
