package logredactionpolicy

import (
	"context"
	"strconv"

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

	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	openapingv1beta2 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/nextgen/v1beta2"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/eventbus"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/grpc/metadata"
)

func (c serverImpl) UpdateLogRedactionPolicy(
	ctx context.Context,
	req *openapingv1beta2.UpdateLogRedactionPolicyRequest,
) (*openapingv1beta2.LogRedactionPolicy, error) {
	ctx, span := tracer.Start(ctx, "UpdateLogRedactionPolicy")
	defer span.End()

	var (
		err                       error
		reqMeta                   *metadata.RequestMeta
		requestLogRedactionPolicy *globalngv1.LogRedactionPolicy
		updatedLogRedactionPolicy *globalngv1.LogRedactionPolicy
	)

	detailsFunc := func() auditlog.Details {
		details := eventbus.NewAuditLogDetails(eventbus.TierTypePremium)
		details[auditlog.KeyNewLogRedactionPolicy] = req.GetLogRedactionPolicy().GetRedactLog()
		return details
	}

	defer func() {
		if !req.ValidateOnly {
			c.auditLogSender.SubmitAuditLogForNextgen(ctx, auditlog.EventUpdateLogRedactionPolicy, 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")
	}
	clusterId, err := strconv.ParseUint(req.GetTidbId(), 10, 64)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid cluster id")
	}

	req.LogRedactionPolicy.TidbId = strconv.FormatUint(clusterId, 10)
	requestLogRedactionPolicy, err = cvtNextgenLogRedactionPolicy(req.GetLogRedactionPolicy())
	if err != nil {
		return nil, err
	}

	updatedLogRedactionPolicy, err = c.nextgenCli.UpdateLogRedactionPolicy(
		ctx,
		&globalngv1.UpdateLogRedactionPolicyRequest{
			LogRedactionPolicy: requestLogRedactionPolicy,
			ValidateOnly:       req.GetValidateOnly(),
		},
	)
	if err != nil {
		return nil, err
	}
	return cvtOpenAPILogRedactionPolicy(updatedLogRedactionPolicy), nil
}

func cvtOpenAPILogRedactionPolicy(
	logRedactionPolicy *globalngv1.LogRedactionPolicy,
) *openapingv1beta2.LogRedactionPolicy {
	return &openapingv1beta2.LogRedactionPolicy{
		TidbId:    strconv.FormatUint(logRedactionPolicy.GetClusterId(), 10),
		RedactLog: logRedactionPolicy.RedactLog,
	}
}

func cvtNextgenLogRedactionPolicy(
	logRedactionPolicy *openapingv1beta2.LogRedactionPolicy,
) (*globalngv1.LogRedactionPolicy, bizerr.BizError) {
	clusterId, err := strconv.ParseUint(logRedactionPolicy.GetTidbId(), 10, 64)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid cluster id")
	}
	return &globalngv1.LogRedactionPolicy{
		ClusterId: clusterId,
		RedactLog: logRedactionPolicy.RedactLog,
	}, nil
}
