package cluster

import (
	"context"

	ec2v1beta1 "github.com/crossplane-contrib/provider-aws/apis/ec2/v1beta1"
	"github.com/pingcap/errors"
	agentv1 "github.com/tidbcloud/observability/agent-control-server/api/v1"
	"k8s.io/apimachinery/pkg/types"
	"sigs.k8s.io/controller-runtime/pkg/client"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"

	xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	"github.com/tidbcloud/eks-provider/api/v1alpha1"
	compatcst "github.com/tidbcloud/infra-provider/pkg/compat/consts"
	"github.com/tidbcloud/infra-provider/pkg/namer"
)

func BuildEKSCloudTopology(
	ctx context.Context,
	cli client.Client,
	network *cloudv1.Network,
	networkSpec *v1alpha1.EKSNetworkSpec,
	sg string,
	subnets []string,
) (agentv1.CloudTopologyType, error) {

	if sg == "" {
		sg = networkSpec.SecurityGroupId
	}
	if subnets == nil {
		subnets = networkSpec.SubnetIds
	}
	agentinfo := agentv1.CloudTopologyType{
		EKS: &agentv1.EKSVPCConfigType{
			AssumeRoleArn:    networkSpec.AssumeRoleArn,
			AssumeExternalId: networkSpec.AssumeExternalId,
			VpcID:            networkSpec.VpcId,
			SecurityGroupID:  sg,
			NodeSubnetIDs:    subnets,
		},
	}
	//if not compat network, we set ref to crossplane vpc
	if _, ok := network.Annotations[compatcst.CompatFlagAnnotation]; !ok {
		vpcName := namer.UniqueIdentifier(network.ObjectMeta)
		var vpc ec2v1beta1.VPC
		if err := cli.Get(ctx, types.NamespacedName{
			Name: vpcName,
		}, &vpc); err != nil {
			return agentv1.CloudTopologyType{}, errors.New("VPC not found")
		}
		agentinfo.EKS.ProviderConfigReference = vpc.GetProviderConfigReference()
	} else {
		// we use fake vpc name to set the provider config reference for avoid the validation check
		// In new arch, this field has no practical use
		agentinfo.EKS.ProviderConfigReference = &xpv1.Reference{
			Name: "comapt-o11y-vpc",
		}
	}
	return agentinfo, nil
}

func BuildGKECloudTopology(networkSpec *v1alpha1.GKENetworkSpec) agentv1.CloudTopologyType {
	return agentv1.CloudTopologyType{
		GKE: &agentv1.GKEVPCConfigType{
			ProjectID: networkSpec.ProjectID,
			Network:   networkSpec.Network,
			Subnets:   networkSpec.Subnets,
		},
	}
}
