package cluster

import (
	"context"
	"errors"
	"strconv"

	"braces.dev/errtrace"
	"github.com/tidbcloud/tiinf/sdk/auditlog"
	"gorm.io/gorm"

	openapidedicatedv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/dedicated/v1beta1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/eventbus"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/constant"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/apimiddleware/bizerror"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/grpc/metadata"
)

func (c *serverImpl) DeleteCluster(
	ctx context.Context,
	req *openapidedicatedv1beta1.DeleteClusterRequest,
) (*openapidedicatedv1beta1.Cluster, error) {
	ctx, span := tracer.Start(ctx, "DeleteCluster")
	defer span.End()
	var (
		err     error
		reqMeta *metadata.RequestMeta
		res     *openapidedicatedv1beta1.Cluster
	)

	detailsFunc := func() auditlog.Details {
		details := eventbus.NewAuditLogDetails(eventbus.TierTypeDedicated)
		details = eventbus.AppendDedicatedClusterDetails(details, res)
		return details
	}
	defer func() {
		if !req.GetValidateOnly() {
			c.auditLogSender.SubmitAuditLog(ctx, auditlog.EventDeleteCluster, reqMeta, detailsFunc, err)
		}
	}()

	// Extract request meta.
	reqMeta, err = metadata.ExtractRequestMetaWithCheckPermission(ctx)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "failed to extract request metadata")
	}

	// Delete from domain service
	var (
		cluster      *entity.Cluster
		customStatus *entity.ClusterCustomStatus
	)
	cluster = &entity.Cluster{}
	cluster.ClusterId, err = strconv.ParseUint(req.ClusterId, 10, 64)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid cluster id")
	}

	cluster, customStatus, err = c.clusterSvc.DeleteCluster(ctx, cluster.ClusterId, false, req.GetValidateOnly())
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, bizerror.NewNotFound(err, "cluster not found")
		} else if errors.Is(err, constant.ErrClusterCustomStatusForbidden) {
			return nil, bizerror.NewForbiddenForClusterCustomStatus(err, customStatus.StatusType.String())
		}
		return nil, bizerror.NewInternal(err, "failed to delete cluster record")
	}

	// delete cluster not need override custom status
	res, err = buildClusterFromEntity(cluster, nil)
	if err != nil {
		return nil, errtrace.Wrap(err)
	}
	return res, nil
}
