package region

import (
	"context"
	"strings"

	"google.golang.org/genproto/googleapis/rpc/errdetails"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	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"
	"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) PlanResourcePoolCidr(
	ctx context.Context,
	req *openapingv1beta2.PlanResourcePoolCidrRequest,
) (*openapingv1beta2.PlanResourcePoolCidrResponse, error) {
	ctx, span := tracer.Start(ctx, "PlanResourcePoolCidr")
	defer span.End()

	requestMeta, err := metadata.ExtractRequestMetaWithCheckPermission(ctx)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "failed to extract request metadata")
	}
	provider, regionID, 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](regionID)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid region")
	}
	highAvailabilityType, err := resourcePoolCIDRHighAvailabilityTypeToGlobal(req.GetHighAvailabilityType())
	if err != nil {
		return nil, err
	}
	response, err := t.nextgenCli.PlanResourcePoolCidr(ctx, &globalngv1.PlanResourcePoolCidrRequest{
		OrganizationId:       requestMeta.OrgID,
		CloudProviderId:      globalcommonv1.CloudProvider_Name(providerValue),
		RegionId:             globalcommonv1.Region_Name(regionValue),
		HighAvailabilityType: highAvailabilityType,
	})
	if err != nil {
		return nil, err
	}
	return planResourcePoolCIDRResponseToOpenAPI(response)
}

func (t serverImpl) ValidateResourcePoolCidr(
	ctx context.Context,
	req *openapingv1beta2.ValidateResourcePoolCidrRequest,
) (*openapingv1beta2.ValidateResourcePoolCidrResponse, error) {
	ctx, span := tracer.Start(ctx, "ValidateResourcePoolCidr")
	defer span.End()

	if req == nil || strings.TrimSpace(req.GetCidr()) == "" {
		withDetails, err := status.New(codes.InvalidArgument, "cidr is required").WithDetails(&errdetails.BadRequest{
			FieldViolations: []*errdetails.BadRequest_FieldViolation{{
				Field:       "cidr",
				Description: "CIDR is required.",
			}},
		})
		if err != nil {
			return nil, status.Error(codes.Internal, "failed to encode request validation error")
		}
		return nil, withDetails.Err()
	}
	requestMeta, err := metadata.ExtractRequestMetaWithCheckPermission(ctx)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "failed to extract request metadata")
	}
	provider, regionID, 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](regionID)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid region")
	}
	highAvailabilityType, err := resourcePoolCIDRHighAvailabilityTypeToGlobal(req.GetHighAvailabilityType())
	if err != nil {
		return nil, err
	}
	response, err := t.nextgenCli.ValidateResourcePoolCidr(ctx, &globalngv1.ValidateResourcePoolCidrRequest{
		OrganizationId:       requestMeta.OrgID,
		CloudProviderId:      globalcommonv1.CloudProvider_Name(providerValue),
		RegionId:             globalcommonv1.Region_Name(regionValue),
		Cidr:                 req.GetCidr(),
		HighAvailabilityType: highAvailabilityType,
	})
	if err != nil {
		return nil, err
	}
	return validateResourcePoolCIDRResponseToOpenAPI(response)
}
