package k8scalendar

import (
	"github.com/gin-gonic/gin"
	"github.com/go-logr/logr"
	"go.uber.org/dig"

	"github.com/tidbcloud/devops/api"
	calapi "github.com/tidbcloud/devops/api/k8scalendar"
	ctrl "github.com/tidbcloud/devops/pkg/controller"
	calsvcapi "github.com/tidbcloud/devops/pkg/service/k8scalendar/api"
)

type ControllerParam struct {
	dig.In

	Logger      logr.Logger
	CalendarSvc calsvcapi.API
}

type Controller struct {
	logger      logr.Logger
	calendarSvc calsvcapi.API
}

func NewController(p ControllerParam) ctrl.Controller {
	return &Controller{
		logger:      p.Logger.WithName("K8sCalendarController"),
		calendarSvc: p.CalendarSvc,
	}
}

func (c *Controller) Name() string {
	return "K8sCalendarController"
}

func (c *Controller) RegisterAPI(suite *ctrl.Suite) error {
	g := suite.Router.Group("/k8sCalendar")
	g.GET("/lifecycles", c.ListLifecycles)
	g.POST("/syncNow", c.SyncNow)
	g.POST("/resetNotificationFlags", c.ResetNotificationFlags)
	return nil
}

// ListLifecycles
//
//	@Id				K8sCalendarControllerListLifecycles
//	@Description	list k8s version lifecycles
//	@Tags			K8sCalendarService
//	@Accept			json
//	@Produce		json
//	@Param			req	query		calapi.ListLifecyclesReq	true	"ListLifecyclesReq"
//	@Success		200	{object}	calapi.ListLifecyclesResp
//	@Failure		500	{object}	api.BaseResp
//	@Router			/api/v1/devops/k8sCalendar/lifecycles [get]
func (c *Controller) ListLifecycles(ctx *gin.Context) {
	req := &calapi.ListLifecyclesReq{}
	if err := ctx.ShouldBindQuery(req); err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}
	items, err := c.calendarSvc.ListLifecycles(ctx, req.CloudProvider)
	if err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInternal)
		return
	}
	ctrl.Success(ctx, &calapi.ListLifecyclesResp{Items: items})
}

// SyncNow
//
//	@Id				K8sCalendarControllerSyncNow
//	@Description	force sync k8s version calendar from cloud providers
//	@Tags			K8sCalendarService
//	@Accept			json
//	@Produce		json
//	@Param			req	body		calapi.SyncNowReq	false	"SyncNowReq"
//	@Success		200	{object}	api.BaseResp
//	@Failure		500	{object}	api.BaseResp
//	@Router			/api/v1/devops/k8sCalendar/syncNow [post]
func (c *Controller) SyncNow(ctx *gin.Context) {
	req := &calapi.SyncNowReq{}
	if ctx.Request.ContentLength > 0 {
		if err := ctx.ShouldBindJSON(req); err != nil {
			ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
			return
		}
	} else if err := ctx.ShouldBindQuery(req); err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}
	failOnProviderError := false
	if req.FailOnProviderError != nil {
		failOnProviderError = *req.FailOnProviderError
	}
	if err := c.calendarSvc.ForceSync(ctx, failOnProviderError); err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInternal)
		return
	}
	ctrl.Success(ctx, nil)
}

// ResetNotificationFlags
//
//	@Id				K8sCalendarControllerResetNotificationFlags
//	@Description	reset notification markers for a k8s version lifecycle (by cloud and version)
//	@Tags			K8sCalendarService
//	@Accept			json
//	@Produce		json
//	@Param			req	body		calapi.ResetNotificationFlagsReq	true	"ResetNotificationFlagsReq"
//	@Success		200	{object}	api.BaseResp
//	@Failure		400	{object}	api.BaseResp
//	@Failure		404	{object}	api.BaseResp
//	@Failure		500	{object}	api.BaseResp
//	@Router			/api/v1/devops/k8sCalendar/resetNotificationFlags [post]
func (c *Controller) ResetNotificationFlags(ctx *gin.Context) {
	req := &calapi.ResetNotificationFlagsReq{}
	if err := ctx.ShouldBindJSON(req); err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}
	if err := c.calendarSvc.ResetNotificationFlags(ctx, req.Cloud, req.Version, req.Flags); err != nil {
		ctrl.Fail(ctx, err)
		return
	}
	ctrl.Success(ctx, nil)
}
