package region

import (
	"context"

	"github.com/samber/lo"

	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	openapicommonv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/common/v1beta1"
	openapingv1beta2 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/nextgen/v1beta2"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/apimiddleware/bizerror"
	"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"
)

func (t serverImpl) ListCloudProviders(
	ctx context.Context,
	req *openapingv1beta2.ListCloudProvidersRequest,
) (*openapingv1beta2.ListCloudProvidersResponse, error) {
	ctx, span := tracer.Start(ctx, "ListCloudProviders")
	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
	resp, err := t.nextgenCli.ListCloudProviders(ctx, &globalngv1.ListCloudProvidersRequest{
		OrganizationId: orgId,
		ServicePlan:    common.CvtGlobalServicePlan(req.GetServicePlan()),
		State:          globalcommonv1.CloudProvider_ACTIVE,
	})
	if err != nil {
		return nil, bizerror.NewInternal(err, "failed to list cloud providers")
	}

	thirdProviders, err := t.accountCli.GetTenantThirdPartyAccountProviders(ctx, orgId)
	if err != nil {
		return nil, bizerr.WrapGrpcError(err, "failed to get third party account providers")
	}

	ps := make([]*globalcommonv1.CloudProvider, 0, len(resp.GetCloudProviders()))
	for _, p := range resp.GetCloudProviders() {
		provider := common.GlobalProviderToOpenApi(p.GetId())
		// if third party account providers exist
		if len(thirdProviders) > 0 && !lo.Contains(thirdProviders, provider) {
			continue
		}
		ps = append(ps, p)
	}

	output := make([]openapicommonv1beta1.Region_CloudProvider, 0, len(ps))
	for _, p := range ps {
		provider := common.GlobalProviderToOpenApi(p.GetId())
		output = append(output, provider)
	}

	return &openapingv1beta2.ListCloudProvidersResponse{CloudProviders: output}, nil
}
