package loader

import (
	crossplaneautoscalingv1beta1 "github.com/crossplane-contrib/provider-aws/apis/autoscaling/v1beta1"
	crossplaneec2v1alpha1 "github.com/crossplane-contrib/provider-aws/apis/ec2/v1alpha1"
	crossplaneec2v1beta1 "github.com/crossplane-contrib/provider-aws/apis/ec2/v1beta1"
	crossplaneeksv1alpha1 "github.com/crossplane-contrib/provider-aws/apis/eks/manualv1alpha1"
	crossplanecpeksv1beta1 "github.com/crossplane-contrib/provider-aws/apis/eks/v1beta1"
	crossplaneawsiamv1beta1 "github.com/crossplane-contrib/provider-aws/apis/iam/v1beta1"
	crossplanecpawsv1beta1 "github.com/crossplane-contrib/provider-aws/apis/v1beta1"
	crossplanegkev1beta1 "github.com/crossplane-contrib/provider-gcp/apis/container/v1beta1"
	crossplanegkev1beta2 "github.com/crossplane-contrib/provider-gcp/apis/container/v1beta2"
	ackv1alpha1 "github.com/crossplane-contrib/provider-upjet-alibabacloud/apis/ack/v1alpha1"
	aliplv1alpha1 "github.com/crossplane-contrib/provider-upjet-alibabacloud/apis/privatelink/v1alpha1"
	upboundec2v1beta1 "github.com/upbound/provider-aws/apis/ec2/v1beta1"
	upboundcpeksv1beta1 "github.com/upbound/provider-aws/apis/eks/v1beta1"
	upboundcpeksv1beta2 "github.com/upbound/provider-aws/apis/eks/v1beta2"
	upboundcpawsv1beta1 "github.com/upbound/provider-aws/apis/v1beta1"
	azureksv1beta1 "github.com/upbound/provider-azure/apis/containerservice/v1beta1"
	azurenetworkv1beta2 "github.com/upbound/provider-azure/apis/network/v1beta2"
	azurev1beta1 "github.com/upbound/provider-azure/apis/v1beta1"
	upboundgkev1beta2 "github.com/upbound/provider-gcp/apis/container/v1beta2"
	"k8s.io/apimachinery/pkg/runtime"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"

	clusterserverv1 "github.com/tidbcloud/observability/agent-control-server/api/clusterserver/v1"
	rsv1alpha1 "github.com/tidbcloud/observability/agent-control-server/api/regionalserver/v1alpha1"
	agentv2 "github.com/tidbcloud/observability/agent-control-server/api/v2"
)

func ProviderScheme() *runtime.Scheme {
	scheme := runtime.NewScheme()

	// register common schemes
	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
	utilruntime.Must(agentv2.AddToScheme(scheme))
	utilruntime.Must(rsv1alpha1.AddToScheme(scheme))
	utilruntime.Must(clusterserverv1.AddToScheme(scheme))

	// register aws schemes
	utilruntime.Must(crossplanecpeksv1beta1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(crossplaneautoscalingv1beta1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(crossplanecpawsv1beta1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(crossplaneec2v1alpha1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(crossplaneec2v1beta1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(crossplaneeksv1alpha1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(crossplaneawsiamv1beta1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(upboundcpeksv1beta1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(upboundcpeksv1beta2.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(upboundcpawsv1beta1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(upboundec2v1beta1.SchemeBuilder.AddToScheme(scheme))
	// register gcp schemes
	utilruntime.Must(crossplanegkev1beta1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(crossplanegkev1beta2.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(upboundgkev1beta2.SchemeBuilder.AddToScheme(scheme))

	// resister alicloud schemes
	utilruntime.Must(ackv1alpha1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(aliplv1alpha1.SchemeBuilder.AddToScheme(scheme))

	// register azure schemes
	utilruntime.Must(azureksv1beta1.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(azurenetworkv1beta2.SchemeBuilder.AddToScheme(scheme))
	utilruntime.Must(azurev1beta1.SchemeBuilder.AddToScheme(scheme))

	return scheme
}

func RemoteScheme(fs ...func(s *runtime.Scheme) error) *runtime.Scheme {
	funcs := []func(s *runtime.Scheme) error{
		clientgoscheme.AddToScheme,
	}
	funcs = append(funcs, fs...)

	scheme := runtime.NewScheme()
	for _, f := range funcs {
		utilruntime.Must(f(scheme))
	}
	return scheme
}
