/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package config

import (
	"testing"
)

import (
	"github.com/stretchr/testify/assert"
)

import (
	"dubbo.apache.org/dubbo-go/v3/common/constant"
	_ "dubbo.apache.org/dubbo-go/v3/proxy/proxy_factory"
)

// import (
//
//	"context"
//	"dubbo.apache.org/dubbo-go/v3/config"
//	"dubbo.apache.org/dubbo-go/v3/config/applicationConfig"
//	"dubbo.apache.org/dubbo-go/v3/config/base"
//	"dubbo.apache.org/dubbo-go/v3/config/consumer"
//	"dubbo.apache.org/dubbo-go/v3/config/instance"
//	"dubbo.apache.org/dubbo-go/v3/config/method"
//	registry2 "dubbo.apache.org/dubbo-go/v3/config/registry"
//	"sync"
//	"testing"
//
// )
//
// import (
//
//	"github.com/stretchr/testify/assert"
//
// )
//
// import (
//
//	"dubbo.apache.org/dubbo-go/v3/cluster/cluster_impl"
//	"dubbo.apache.org/dubbo-go/v3/common"
//	"dubbo.apache.org/dubbo-go/v3/common/constant"
//	"dubbo.apache.org/dubbo-go/v3/common/extension"
//	"dubbo.apache.org/dubbo-go/v3/filter"
//	"dubbo.apache.org/dubbo-go/v3/protocol"
//	"dubbo.apache.org/dubbo-go/v3/registry"
//
// )
//
// var regProtocol protocol.Protocol
//
//	func doInitConsumer() {
//		config.consumerConfig = &consumer.Config{
//			BaseConfig: base.Config{
//				applicationConfig.Config: &applicationConfig.Config{
//					Organization: "dubbo_org",
//					Name:         "dubbo",
//					Module:       "module",
//					Version:      "2.6.0",
//					Owner:        "dubbo",
//					Environment:  "test",
//				},
//			},
//
//			Registries: map[string]*registry2.RegistryConfig{
//				"shanghai_reg1": {
//					Protocol:   "mock",
//					TimeoutStr: "2s",
//					Group:      "shanghai_idc",
//					Address:    "127.0.0.1:2181",
//					Username:   "user1",
//					Password:   "pwd1",
//				},
//				"shanghai_reg2": {
//					Protocol:   "mock",
//					TimeoutStr: "2s",
//					Group:      "shanghai_idc",
//					Address:    "127.0.0.2:2181",
//					Username:   "user1",
//					Password:   "pwd1",
//				},
//				"hangzhou_reg1": {
//					Protocol:   "mock",
//					TimeoutStr: "2s",
//					Group:      "hangzhou_idc",
//					Address:    "127.0.0.3:2181",
//					Username:   "user1",
//					Password:   "pwd1",
//				},
//				"hangzhou_reg2": {
//					Protocol:   "mock",
//					TimeoutStr: "2s",
//					Group:      "hangzhou_idc",
//					Address:    "127.0.0.4:2181",
//					Username:   "user1",
//					Password:   "pwd1",
//				},
//			},
//
//			References: map[string]*ReferenceConfig{
//				"MockService": {
//					id: "MockProvider",
//					Params: map[string]string{
//						"serviceid": "soa.mock",
//						"forks":     "5",
//					},
//					Sticky:        false,
//					Registry:      "shanghai_reg1,shanghai_reg2,hangzhou_reg1,hangzhou_reg2",
//					InterfaceName: "com.MockService",
//					Protocol:      "mock",
//					Cluster:       "failover",
//					Loadbalance:   "random",
//					Retries:       "3",
//					Group:         "huadong_idc",
//					Version:       "1.0.0",
//					Methods: []*method.MethodConfig{
//						{
//							Name:        "GetUser",
//							Retries:     "2",
//							LoadBalance: "random",
//						},
//						{
//							Name:        "GetUser1",
//							Retries:     "2",
//							LoadBalance: "random",
//							Sticky:      true,
//						},
//					},
//				},
//			},
//		}
//	}
//
// var mockProvider = new(MockProvider)
//
// type MockProvider struct{}
//
//	func (m *MockProvider) Reference() string {
//		return "MockProvider"
//	}
//
//	func (m *MockProvider) CallBack(res common.CallbackResponse) {
//		// CallBack is a mock function. to implement the interface
//	}
//
//	func doInitConsumerAsync() {
//		doInitConsumer()
//		instance.SetConsumerService(mockProvider)
//		for _, v := range config.consumerConfig.References {
//			v.Async = true
//		}
//	}
//
//	func doInitConsumerWithSingleRegistry() {
//		config.consumerConfig = &consumer.Config{
//			BaseConfig: base.Config{
//				applicationConfig.Config: &applicationConfig.Config{
//					Organization: "dubbo_org",
//					Name:         "dubbo",
//					Module:       "module",
//					Version:      "2.6.0",
//					Owner:        "dubbo",
//					Environment:  "test",
//				},
//			},
//
//			Registry: &registry2.RegistryConfig{
//				Address:  "mock://27.0.0.1:2181",
//				Username: "user1",
//				Password: "pwd1",
//			},
//			Registries: map[string]*registry2.RegistryConfig{},
//
//			References: map[string]*ReferenceConfig{
//				"MockService": {
//					Params: map[string]string{
//						"serviceid": "soa.mock",
//						"forks":     "5",
//					},
//					InterfaceName: "com.MockService",
//					Protocol:      "mock",
//					Cluster:       "failover",
//					Loadbalance:   "random",
//					Retries:       "3",
//					Group:         "huadong_idc",
//					Version:       "1.0.0",
//					Methods: []*method.MethodConfig{
//						{
//							Name:        "GetUser",
//							Retries:     "2",
//							LoadBalance: "random",
//						},
//						{
//							Name:        "GetUser1",
//							Retries:     "2",
//							LoadBalance: "random",
//						},
//					},
//				},
//			},
//		}
//	}
//
//	func TestReferMultiReg(t *testing.T) {
//		doInitConsumer()
//		extension.SetProtocol("registry", GetProtocol)
//		extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
//		for _, reference := range config.consumerConfig.References {
//			reference.Refer(nil)
//			assert.NotNil(t, reference.invoker)
//			assert.NotNil(t, reference.pxy)
//		}
//		config.consumerConfig = nil
//	}
//
//	func TestRefer(t *testing.T) {
//		doInitConsumer()
//		extension.SetProtocol("registry", GetProtocol)
//		extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
//
//		for _, reference := range config.consumerConfig.References {
//			reference.Refer(nil)
//			assert.Equal(t, "soa.mock", reference.Params["serviceid"])
//			assert.NotNil(t, reference.invoker)
//			assert.NotNil(t, reference.pxy)
//		}
//		config.consumerConfig = nil
//	}
//
//	func TestReferAsync(t *testing.T) {
//		doInitConsumerAsync()
//		extension.SetProtocol("registry", GetProtocol)
//		extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
//
//		for _, reference := range config.consumerConfig.References {
//			reference.Refer(nil)
//			assert.Equal(t, "soa.mock", reference.Params["serviceid"])
//			assert.NotNil(t, reference.invoker)
//			assert.NotNil(t, reference.pxy)
//			assert.NotNil(t, reference.pxy.GetCallback())
//		}
//		config.consumerConfig = nil
//	}
//
//	func TestReferP2P(t *testing.T) {
//		doInitConsumer()
//		extension.SetProtocol("dubbo", GetProtocol)
//		mockFilter()
//		m := config.consumerConfig.References["MockService"]
//		m.URL = "dubbo://127.0.0.1:20000"
//
//		for _, reference := range config.consumerConfig.References {
//			reference.Refer(nil)
//			assert.NotNil(t, reference.invoker)
//			assert.NotNil(t, reference.pxy)
//		}
//		config.consumerConfig = nil
//	}
//
//	func TestReferMultiP2P(t *testing.T) {
//		doInitConsumer()
//		extension.SetProtocol("dubbo", GetProtocol)
//		mockFilter()
//		m := config.consumerConfig.References["MockService"]
//		m.URL = "dubbo://127.0.0.1:20000;dubbo://127.0.0.2:20000"
//
//		for _, reference := range config.consumerConfig.References {
//			reference.Refer(nil)
//			assert.NotNil(t, reference.invoker)
//			assert.NotNil(t, reference.pxy)
//		}
//		config.consumerConfig = nil
//	}
//
//	func TestReferMultiP2PWithReg(t *testing.T) {
//		doInitConsumer()
//		extension.SetProtocol("dubbo", GetProtocol)
//		extension.SetProtocol("registry", GetProtocol)
//		mockFilter()
//		m := config.consumerConfig.References["MockService"]
//		m.URL = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
//
//		for _, reference := range config.consumerConfig.References {
//			reference.Refer(nil)
//			assert.NotNil(t, reference.invoker)
//			assert.NotNil(t, reference.pxy)
//		}
//		config.consumerConfig = nil
//	}
//
//	func TestImplement(t *testing.T) {
//		doInitConsumer()
//		extension.SetProtocol("registry", GetProtocol)
//		extension.SetCluster(constant.ZONEAWARE_CLUSTER_NAME, cluster_impl.NewZoneAwareCluster)
//		for _, reference := range config.consumerConfig.References {
//			reference.Refer(nil)
//			reference.Implement(&config.MockService{})
//			assert.NotNil(t, reference.GetRPCService())
//
//		}
//		config.consumerConfig = nil
//	}
//
//	func TestForking(t *testing.T) {
//		doInitConsumer()
//		extension.SetProtocol("dubbo", GetProtocol)
//		extension.SetProtocol("registry", GetProtocol)
//		mockFilter()
//		m := config.consumerConfig.References["MockService"]
//		m.URL = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
//
//		for _, reference := range config.consumerConfig.References {
//			reference.Refer(nil)
//			forks := int(reference.invoker.GetURL().GetParamInt(constant.FORKS_KEY, constant.DEFAULT_FORKS))
//			assert.Equal(t, 5, forks)
//			assert.NotNil(t, reference.pxy)
//			assert.NotNil(t, reference.Cluster)
//		}
//		config.consumerConfig = nil
//	}
//
//	func TestSticky(t *testing.T) {
//		doInitConsumer()
//		extension.SetProtocol("dubbo", GetProtocol)
//		extension.SetProtocol("registry", GetProtocol)
//		mockFilter()
//		m := config.consumerConfig.References["MockService"]
//		m.URL = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000"
//
//		reference := config.consumerConfig.References["MockService"]
//		reference.Refer(nil)
//		referenceSticky := reference.invoker.GetURL().GetParam(constant.STICKY_KEY, "false")
//		assert.Equal(t, "false", referenceSticky)
//
//		method0StickKey := reference.invoker.GetURL().GetMethodParam(reference.Methods[0].Name, constant.STICKY_KEY, "false")
//		assert.Equal(t, "false", method0StickKey)
//		method1StickKey := reference.invoker.GetURL().GetMethodParam(reference.Methods[1].Name, constant.STICKY_KEY, "false")
//		assert.Equal(t, "true", method1StickKey)
//	}
//
//	func GetProtocol() protocol.Protocol {
//		if regProtocol != nil {
//			return regProtocol
//		}
//		return newRegistryProtocol()
//	}
//
//	func newRegistryProtocol() protocol.Protocol {
//		return &mockRegistryProtocol{}
//	}
//
// type mockRegistryProtocol struct {
// }
//
//	func (*mockRegistryProtocol) Refer(url *common.URL) protocol.Invoker {
//		return protocol.NewBaseInvoker(url)
//	}
//
//	func (*mockRegistryProtocol) Export(invoker protocol.Invoker) protocol.Exporter {
//		registryURL := getRegistryURL(invoker)
//		if registryURL.Protocol == "service-discovery" {
//			metaDataService, err := extension.GetLocalMetadataService("")
//			if err != nil {
//				panic(err)
//			}
//			ok, err := metaDataService.ExportURL(invoker.GetURL().SubURL.Clone())
//			if err != nil {
//				panic(err)
//			}
//			if !ok {
//				panic("The URL has been registry!")
//			}
//		}
//		return protocol.NewBaseExporter("test", invoker, &sync.Map{})
//	}
//
//	func (*mockRegistryProtocol) Destroy() {
//		// Destroy is a mock function
//	}
//
//	func getRegistryURL(invoker protocol.Invoker) *common.URL {
//		// here add * for return a new url
//		url := invoker.GetURL()
//		// if the protocol == registry ,set protocol the registry value in url.params
//		if url.Protocol == constant.REGISTRY_PROTOCOL {
//			protocol := url.GetParam(constant.REGISTRY_KEY, "")
//			url.Protocol = protocol
//		}
//		return url
//	}
//
//	func (p *mockRegistryProtocol) GetRegistries() []registry.Registry {
//		return []registry.Registry{&config.mockServiceDiscoveryRegistry{}}
//	}
//
//	func mockFilter() {
//		consumerFiler := &mockShutdownFilter{}
//		extension.SetFilter(constant.GracefulShutdownConsumerFilterKey, func() filter.Filter {
//			return consumerFiler
//		})
//	}
//
// type mockShutdownFilter struct {
// }
//
// // Invoke adds the requests count and block the new requests if applicationConfig is closing
//
//	func (gf *mockShutdownFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
//		return invoker.Invoke(ctx, invocation)
//	}
//
// // OnResponse reduces the number of active processes then return the process result
//
//	func (gf *mockShutdownFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
//		return result
//	}
func TestNewReferenceConfigBuilder(t *testing.T) {
	registryConfig := NewRegistryConfigWithProtocolDefaultPort("nacos")
	protocolConfig := NewProtocolConfigBuilder().
		SetName("dubbo").
		SetPort("20000").
		Build()
	config := NewReferenceConfigBuilder().
		SetInterface("org.apache.dubbo.HelloService").
		SetRegistryIDs("nacos").
		SetGeneric(false).
		SetCluster("cluster").
		SetSerialization("serialization").
		SetProtocol("dubbo").
		Build()

	config.rootConfig = NewRootConfigBuilder().
		SetProtocols(map[string]*ProtocolConfig{"dubbo": protocolConfig}).
		SetRegistries(map[string]*RegistryConfig{"nacos": registryConfig}).
		Build()

	assert.Equal(t, config.Prefix(), constant.ReferenceConfigPrefix+config.InterfaceName+".")
	proxy := config.GetProxy()
	assert.Nil(t, proxy)

	values := config.getURLMap()
	assert.Equal(t, values.Get(constant.GroupKey), "")

	invoker := config.GetInvoker()
	assert.Nil(t, invoker)
}
