package cluster

import (
	"fmt"
	"strconv"

	"github.com/gin-gonic/gin"
	userapiv1 "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/api/core-server/user/v1"
	mgmtv1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"

	"github.com/tidbcloud/devops/api"
	clusterapi "github.com/tidbcloud/devops/api/cluster"
	ctrl "github.com/tidbcloud/devops/pkg/controller"
	"github.com/tidbcloud/devops/pkg/infra/consts"
)

// ListDedicatedToPremiumPrechecks
//
//	@Id				ListDedicatedToPremiumPrechecks
//	@Description	list dedicated to premium migration prechecks
//	@Tags			ClusterService
//	@Accept			json
//	@Produce		json
//	@Param			req	query		clusterapi.ListDedicatedToPremiumPrechecksReq	false	"request param"
//	@Success		200	{object}	clusterapi.ListDedicatedToPremiumPrechecksResp
//	@Failure		400	{object}	api.BaseResp
//	@Failure		500	{object}	api.BaseResp
//	@Router			/api/v1/devops/cluster/migration/dedicate2premium/prechecks [get]
func (c *ClusterController) ListDedicatedToPremiumPrechecks(ctx *gin.Context) {
	req := &clusterapi.ListDedicatedToPremiumPrechecksReq{}
	if err := ctx.ShouldBindQuery(req); err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}
	if req.Page == 0 || req.PerPage == 0 || req.PerPage > 100 {
		ctrl.FailWithCode(ctx, fmt.Errorf("page must be greater than 0 and per_page must be between 1 and 100"), api.ErrCodeInvalidArgument)
		return
	}
	var sourceClusterID uint64
	if req.SourceClusterID != "" {
		var err error
		sourceClusterID, err = strconv.ParseUint(req.SourceClusterID, 10, 64)
		if err != nil {
			ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
			return
		}
	}

	result, err := c.coreSvcCli.Mgmt.DedicatedToPremiumPrecheck.ListDedicatedToPremiumPrechecks(ctx, &mgmtv1.ListDedicatedToPremiumPrechecksRequest{
		SourceClusterId: sourceClusterID,
		Page:            req.Page,
		PageSize:        req.PerPage,
	})
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	ctrl.Success(ctx, &clusterapi.ListDedicatedToPremiumPrechecksResp{
		Items: clusterapi.BuildDedicatedToPremiumPrechecks(result.GetPrechecks()),
		Total: result.GetTotal(),
	})
}

// CreateDedicatedToPremiumPrecheck
//
//	@Id				CreateDedicatedToPremiumPrecheck
//	@Description	create a dedicated to premium migration precheck
//	@Tags			ClusterService
//	@Accept			json
//	@Produce		json
//	@Param			req	body		clusterapi.CreateDedicatedToPremiumPrecheckReq	true	"request param"
//	@Success		200	{object}	clusterapi.DedicatedToPremiumPrecheckResp
//	@Failure		400	{object}	api.BaseResp
//	@Failure		401	{object}	api.BaseResp
//	@Failure		500	{object}	api.BaseResp
//	@Router			/api/v1/devops/cluster/migration/dedicate2premium/prechecks [post]
func (c *ClusterController) CreateDedicatedToPremiumPrecheck(ctx *gin.Context) {
	user, ok := ctx.Get(consts.CtxUserProfile)
	if !ok {
		ctrl.FailWithCode(ctx, fmt.Errorf("user profile not found"), api.ErrCodeUnauthenticated)
		return
	}
	userProfile := user.(*userapiv1.PrincipalProfile)

	req := &clusterapi.CreateDedicatedToPremiumPrecheckReq{}
	if err := ctx.ShouldBindJSON(req); err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}
	clusterID, err := strconv.ParseUint(req.SourceClusterID, 10, 64)
	if err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}
	var targetProjectID uint64
	if req.TargetPremiumProjectID != "" {
		targetProjectID, err = strconv.ParseUint(req.TargetPremiumProjectID, 10, 64)
		if err != nil {
			ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
			return
		}
	}

	precheck, err := c.coreSvcCli.Mgmt.DedicatedToPremiumPrecheck.CreateDedicatedToPremiumPrecheck(ctx, &mgmtv1.CreateDedicatedToPremiumPrecheckRequest{
		SourceClusterId:        clusterID,
		MigrationAccountEmail:  req.MigrationAccountEmail,
		TargetPremiumProjectId: targetProjectID,
		Applicant:              userProfile.UserEmail,
	})
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	ctrl.Success(ctx, &clusterapi.DedicatedToPremiumPrecheckResp{
		Precheck: clusterapi.BuildDedicatedToPremiumPrecheck(precheck),
	})
}

// GetDedicatedToPremiumPrecheck
//
//	@Id				GetDedicatedToPremiumPrecheck
//	@Description	get a dedicated to premium migration precheck
//	@Tags			ClusterService
//	@Accept			json
//	@Produce		json
//	@Param			precheck_id	path		string	true	"precheck id"
//	@Success		200			{object}	clusterapi.DedicatedToPremiumPrecheckResp
//	@Failure		400			{object}	api.BaseResp
//	@Failure		500			{object}	api.BaseResp
//	@Router			/api/v1/devops/cluster/migration/dedicate2premium/prechecks/{precheck_id} [get]
func (c *ClusterController) GetDedicatedToPremiumPrecheck(ctx *gin.Context) {
	precheckID, err := strconv.ParseUint(ctx.Param("precheck_id"), 10, 64)
	if err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}

	precheck, err := c.coreSvcCli.Mgmt.DedicatedToPremiumPrecheck.GetDedicatedToPremiumPrecheck(ctx, &mgmtv1.GetDedicatedToPremiumPrecheckRequest{
		Id: precheckID,
	})
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	ctrl.Success(ctx, &clusterapi.DedicatedToPremiumPrecheckResp{
		Precheck: clusterapi.BuildDedicatedToPremiumPrecheck(precheck),
	})
}
