package operation

import (
	"fmt"

	"github.com/tidbcloud/devops/api"
	opapi "github.com/tidbcloud/devops/api/operation"
	ctrl "github.com/tidbcloud/devops/pkg/controller"
	opsvc "github.com/tidbcloud/devops/pkg/service/operation"

	"github.com/gin-gonic/gin"
)

// ListOperations
//
//	@Id				OperationControllerListOperations
//	@Description	list operations
//	@Tags			OperationController
//	@Accept			json
//	@Produce		json
//	@Param			req	query		opapi.ListOperationReq	false	"request param"
//	@Success		200	{object}	opapi.ListOperationResp
//	@Router			/api/v1/devops/operation/operations [get]
func (c *OperationController) ListOperations(ctx *gin.Context) {
	req := &opapi.ListOperationReq{}
	err := ctx.ShouldBindQuery(req)
	if err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}

	param := opsvc.ListOperationParam{
		Target:     req.Target,
		Categories: req.Categories,
	}
	ops, err := c.opSvc.ListOperations(ctx, param)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	resp := &opapi.ListOperationResp{
		Total:      int64(len(ops)),
		Operations: ops,
	}
	ctrl.Success(ctx, resp)

}

// GetOperation
//
//	@Id				OperationControllerGetOperation
//	@Description	get a operation
//	@Tags			OperationController
//	@Accept			json
//	@Produce		json
//	@Param			operation_name	path		string					true	"operation name"
//	@Param			req				query		opapi.GetOperationReq	false	"request param"
//	@Success		200				{object}	opapi.GetOperationResp
//	@Router			/api/v1/devops/operation/operations/{operation_name} [get]
func (c *OperationController) GetOperation(ctx *gin.Context) {
	name := ctx.Param("operation_name")
	if name == "" {
		ctrl.FailWithCode(ctx, fmt.Errorf("name is required"), api.ErrCodeInvalidArgument)
		return
	}

	req := &opapi.GetOperationReq{}
	err := ctx.ShouldBindQuery(req)
	if err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
	}

	param := opsvc.GetOperationParam{
		InjectParam: req.InjectParam,
		TargetType:  req.TargetType,
		TargetID:    req.TargetID,
		ServicePlan: req.ServicePlan,
	}
	op, err := c.opSvc.GetOperation(ctx, name, param)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	resp := &opapi.GetOperationResp{Operation: op}
	ctrl.Success(ctx, resp)
}

// ListOperationCategories
//
//	@Id				OperationControllerListOperationCategories
//	@Description	list operation categories
//	@Tags			OperationController
//	@Accept			json
//	@Produce		json
//	@Success		200	{object}	opapi.ListOperationCategoryResp
//	@Router			/api/v1/devops/operation/operations/categories [get]
func (c *OperationController) ListOperationCategories(ctx *gin.Context) {
	categories, err := c.opSvc.ListOperationCategories(ctx)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	resp := &opapi.ListOperationCategoryResp{
		Categories: categories,
	}
	ctrl.Success(ctx, resp)
}
