package byocvpcpeering

import (
	dataplanemanagerv1 "github.com/tidbcloud/cluster-service-ng/api/tidbcloud/dataplane-manager/v1"

	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/enum"
)

func cvtDataplanePeeringToGlobal(
	clusterID uint64,
	peering *dataplanemanagerv1.VpcPeering,
) (*entity.VpcPeering, bizerr.BizError) {
	if peering == nil {
		return nil, bizerr.New(bizerr.ErrCodeParams, "vpc peering is required")
	}

	out := &globalngv1.VpcPeering{
		ClusterId:         clusterID,
		Id:                cvtVpcPeeringID(peering),
		State:             cvtVpcPeeringState(peering.GetStatus()),
		TidbCloudVpcCidr:  peering.GetSourceCidrBlock(),
		CustomerVpcCidr:   peering.GetDestinationCidrBlock(),
		CloudProviderId:   globalcommonv1.CloudProvider_NAME_UNSPECIFIED,
		TidbCloudRegionId: globalcommonv1.Region_NAME_UNSPECIFIED,
		CustomerRegionId:  globalcommonv1.Region_NAME_UNSPECIFIED,
	}

	if aws := peering.GetAws(); aws != nil {
		out.CloudProviderId = globalcommonv1.CloudProvider_AWS
		out.TidbCloudAccountId = aws.GetSourceAccountId()
		out.CustomerAccountId = aws.GetDestinationAccountId()
		out.TidbCloudVpcId = aws.GetSourceVpcId()
		out.CustomerVpcId = aws.GetDestinationVpcId()

		sourceRegion, err := enum.RegionFromString(globalcommonv1.CloudProvider_AWS.String(), aws.GetSourceRegion())
		if err != nil {
			return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid source region: %s", aws.GetSourceRegion())
		}
		destinationRegion, err := enum.RegionFromString(globalcommonv1.CloudProvider_AWS.String(), aws.GetDestinationRegion())
		if err != nil {
			return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid destination region: %s", aws.GetDestinationRegion())
		}
		out.TidbCloudRegionId = sourceRegion
		out.CustomerRegionId = destinationRegion
	}

	if ali := peering.GetAli(); ali != nil {
		out.CloudProviderId = globalcommonv1.CloudProvider_ALICLOUD
		out.TidbCloudAccountId = ali.GetSourceAccountId()
		out.CustomerAccountId = ali.GetDestinationAccountId()
		out.TidbCloudVpcId = ali.GetSourceVpcId()
		out.CustomerVpcId = ali.GetDestinationVpcId()

		sourceRegion, err := enum.RegionFromString(globalcommonv1.CloudProvider_ALICLOUD.String(), ali.GetSourceRegion())
		if err != nil {
			return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid source region: %s", ali.GetSourceRegion())
		}
		destinationRegion, err := enum.RegionFromString(globalcommonv1.CloudProvider_ALICLOUD.String(), ali.GetDestinationRegion())
		if err != nil {
			return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid destination region: %s", ali.GetDestinationRegion())
		}
		out.TidbCloudRegionId = sourceRegion
		out.CustomerRegionId = destinationRegion
	}

	return &entity.VpcPeering{VpcPeering: out}, nil
}

func cvtVpcPeeringID(peering *dataplanemanagerv1.VpcPeering) string {
	// Expose the cloud provider's peering connection ID as the stable peering ID
	// so both list/get APIs refer to the same identifier visible to customers.
	if aws := peering.GetAws(); aws != nil && aws.GetVpcPeeringConnectionId() != "" {
		return aws.GetVpcPeeringConnectionId()
	}
	if ali := peering.GetAli(); ali != nil && ali.GetVpcPeeringConnectionId() != "" {
		return ali.GetVpcPeeringConnectionId()
	}
	return peering.GetId()
}

func cvtVpcPeeringState(state dataplanemanagerv1.VpcPeering_Status) globalngv1.VpcPeering_State {
	switch state {
	case dataplanemanagerv1.VpcPeering_PENDING:
		return globalngv1.VpcPeering_PENDING
	case dataplanemanagerv1.VpcPeering_FAILED:
		return globalngv1.VpcPeering_FAILED
	case dataplanemanagerv1.VpcPeering_ACTIVE:
		return globalngv1.VpcPeering_ACTIVE
	default:
		return globalngv1.VpcPeering_STATE_UNSPECIFIED
	}
}
