package tidbxinstance

import (
	"context"
	"time"

	"github.com/samber/lo"
	accountsdk "github.com/tidbcloud/account/idl/pbgen/proto/account"

	bffv1beta2 "github.com/tidbcloud/tidb-management-service/api/spec/bff/cluster_management/v1beta2"
	openapicommonv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/common/v1beta1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/repository"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/grpc/metadata"
)

const starterClusterInventoryLimit = 100

var starterUnlimitedFeatureFlags = []string{
	"instance_capacity_plan_billed_overage",
	"instance_capacity_plan_free_overage",
}

func (s *TiDBServer) GetClusterInventory(
	ctx context.Context,
	_ *bffv1beta2.GetClusterInventoryRequest,
) (resp *bffv1beta2.GetClusterInventoryResponse, err error) {
	startTime := time.Now()
	defer func() {
		recordQueryAPIMetrics(apiGetClusterInventory, time.Since(startTime).Seconds(), err)
	}()

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

	count, err := s.clusterRepo.CountClusterByFilter(
		ctx,
		&repository.ClusterFilter{
			OrganizationIds: []uint64{reqMeta.OrgID},
			ServicePlans:    []string{openapicommonv1beta1.ServicePlan_Starter.String()},
			QueryDeleted:    false,
			DeployType:      entity.DeployTypeServerless,
		},
	)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeDB, "failed to count starter clusters")
	}

	limit := int32(starterClusterInventoryLimit)
	hitFlagNames, err := s.accountCli.ListHitFeatureFlagNames(ctx, &accountsdk.ListHitFeatureFlagNamesReq{OrgId: reqMeta.OrgID})
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeUnknown, "failed to query starter inventory feature flags")
	}
	if lo.ContainsBy(hitFlagNames, func(flagName string) bool {
		return lo.Contains(starterUnlimitedFeatureFlags, flagName)
	}) {
		limit = 0
	}

	return &bffv1beta2.GetClusterInventoryResponse{
		Inventories: []*bffv1beta2.ClusterInventoryItem{
			{
				ServicePlan:  openapicommonv1beta1.ServicePlan_Starter,
				Limit:        limit,
				CurrentCount: int32(count),
			},
		},
	}, nil
}
