package quota

import (
	"context"

	"go.opentelemetry.io/otel"

	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/nextgenglobal"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/apimiddleware/bizerror"
	appcommon "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/common"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/grpc/metadata"
)

var tracer = otel.Tracer("App.nextgen.Quota")

type serverImpl struct {
	nextgenCli nextgenglobal.NextGenGlobal
}

func NewServer(
	nextgenCli nextgenglobal.NextGenGlobal,
) openapingv1beta2.QuotaServiceServer {
	return &serverImpl{
		nextgenCli: nextgenCli,
	}
}

func (s serverImpl) ListQuotas(ctx context.Context,
	request *openapingv1beta2.ListQuotasRequest,
) (*openapingv1beta2.ListQuotasResponse, error) {
	ctx, span := tracer.Start(ctx, "ListQuotas")
	defer span.End()

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

	orgId := reqMeta.OrgID

	quotas, err := s.nextgenCli.ListOrgRcuQuotas(ctx, &globalngv1.ListOrgRcuQuotasRequest{
		OrganizationId: orgId,
	})
	if err != nil {
		return nil, bizerror.NewInternal(err, "failed to list quotas")
	}

	outQuotas := make([]*openapingv1beta2.Quota, 0, len(quotas.RcuQuotas))
	for _, quota := range quotas.RcuQuotas {
		outQuotas = append(outQuotas, cvtOpenAPIQuota(quota))
	}

	return &openapingv1beta2.ListQuotasResponse{
		Quotas: outQuotas,
	}, nil
}

func cvtOpenAPIQuota(
	quota *globalngv1.RcuQuota,
) *openapingv1beta2.Quota {
	return &openapingv1beta2.Quota{
		ServicePlan:              appcommon.CvtOpenAPIServicePlan(quota.ServicePlan),
		InstanceMaxRcu:           int64(quota.InstanceMaxRcu),
		TotalMaxRcu:              int64(quota.TotalMaxRcu),
		BustyRatio:               quota.BustyRatio,
		BurstyRatio:              quota.BurstyRatio,
		MinimalRcuBaseline:       int64(quota.MinimalRcuBaseline),
		MinimalRcuCoefficient:    quota.MinimalRcuCoefficient,
		OrganizationId:           int64(quota.OrganizationId),
		ScaleDownCooldownMinutes: int64(quota.ScaleDownCooldownMinutes),
	}
}
