package region

import (
	"context"
	"strconv"

	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	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"
	resourcepoolapp "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/resourcepool"
	"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/enum"
	"github.com/tidbcloud/tidb-management-service/utilities/grpc/metadata"
)

func (t serverImpl) ListNodeSpecs(
	ctx context.Context,
	req *openapingv1beta2.ListNodeSpecsRequest,
) (*openapingv1beta2.ListNodeSpecsResponse, error) {
	ctx, span := tracer.Start(ctx, "ListNodeSpecs")
	defer span.End()

	reqMeta, err := metadata.ExtractRequestMetaWithCheckPermission(ctx)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "failed to extract request metadata")
	}
	organizationID, err := strconv.ParseUint(req.GetOrganizationId(), 10, 64)
	if err != nil || organizationID == 0 || organizationID != reqMeta.OrgID {
		return nil, bizerr.New(bizerr.ErrCodePermission, "organization_id does not match the authenticated organization")
	}
	if req.GetPageSize() < 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "page_size must not be negative")
	}

	provider, region, err := common.ParseOpenApiRegionNameOrId(req.GetRegionId())
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid region_id")
	}
	providerValue, err := enum.FromString[globalcommonv1.CloudProvider_Name](provider)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid region provider")
	}
	regionValue, err := enum.FromString[globalcommonv1.Region_Name](region)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid region")
	}

	var componentType globalngv1.NodeSpecComponentType
	switch req.GetComponentType() {
	case openapingv1beta2.NodeSpecComponentType_NODE_SPEC_COMPONENT_TYPE_TIKV:
		componentType = globalngv1.NodeSpecComponentType_NODE_SPEC_COMPONENT_TYPE_TIKV
	case openapingv1beta2.NodeSpecComponentType_NODE_SPEC_COMPONENT_TYPE_TIFLASH:
		componentType = globalngv1.NodeSpecComponentType_NODE_SPEC_COMPONENT_TYPE_TIFLASH
	default:
		return nil, bizerr.New(bizerr.ErrCodeParams, "component_type must be TIKV or TIFLASH")
	}

	response, err := t.nextgenCli.ListNodeSpecs(ctx, &globalngv1.ListNodeSpecsRequest{
		OrganizationId:  organizationID,
		CloudProviderId: globalcommonv1.CloudProvider_Name(providerValue),
		RegionId:        globalcommonv1.Region_Name(regionValue),
		ComponentType:   componentType,
		PageSize:        req.GetPageSize(),
		PageToken:       req.GetPageToken(),
	})
	if err != nil {
		return nil, err
	}
	return resourcepoolapp.NodeSpecsResponseToOpenAPI(response), nil
}
