package cluster

import (
	"context"
	"errors"
	"strconv"
	"time"

	"github.com/tidbcloud/tiinf/sdk/auditlog"
	"gorm.io/gorm"

	openapiserverlessv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/serverless/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 *openapiserverlessv1beta1.DeleteClusterRequest,
) (res *openapiserverlessv1beta1.Cluster, err error) {
	var (
		reqMeta *metadata.RequestMeta
	)
	tenantID := unknownTenantID
	startTime := time.Now()
	defer func() {
		recordWriteClusterAPIMetrics(apiDeleteCluster, tenantID, time.Since(startTime).Seconds(), err)
	}()

	detailsFunc := func() auditlog.Details {
		details := eventbus.NewAuditLogDetails(eventbus.TierTypeServerless)
		details = eventbus.AppendServerlessClusterDetails(details, res)
		return details
	}
	defer func() {
		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")
	}
	tenantID = strconv.FormatUint(reqMeta.OrgID, 10)

	cluster := &entity.Cluster{}
	cluster.ClusterId, err = strconv.ParseUint(req.GetClusterId(), 10, 64)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid cluster id")
	}

	// Delete cluster in domain service
	cluster, customStatus, err := c.clusterSvc.DeleteCluster(ctx, cluster.ClusterId)
	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, openapiserverlessv1beta1.ClusterView_BASIC)

	return res, err
}
