/*
 * 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"
	"go.uber.org/atomic"
)

import (
	"dubbo.apache.org/dubbo-go/v3/common"
	"dubbo.apache.org/dubbo-go/v3/common/extension"
)

func doInitProvider() {
	providerConfig = &ProviderConfig{
		BaseConfig: BaseConfig{
			ApplicationConfig: &ApplicationConfig{
				Organization: "dubbo_org",
				Name:         "dubbo",
				Module:       "module",
				Version:      "2.6.0",
				Owner:        "dubbo",
				Environment:  "test",
			},
			Remotes: map[string]*RemoteConfig{
				"test1": {
					Address:    "127.0.0.5:2181",
					TimeoutStr: "5s",
					Username:   "user1",
					Password:   "pwd1",
					Params:     nil,
				},
			},
			ServiceDiscoveries: map[string]*ServiceDiscoveryConfig{
				"mock_servicediscovery": {
					Protocol:  "mock",
					RemoteRef: "test1",
				},
			},
			MetadataReportConfig: &MetadataReportConfig{
				Protocol:  "mock",
				RemoteRef: "test1",
			},
		},
		Services: map[string]*ServiceConfig{
			"MockService": {
				InterfaceName: "com.MockService",
				Protocol:      "mock",
				Registry:      "shanghai_reg1,shanghai_reg2,hangzhou_reg1,hangzhou_reg2,hangzhou_service_discovery_reg",
				Cluster:       "failover",
				Loadbalance:   "random",
				Retries:       "3",
				Group:         "huadong_idc",
				Version:       "1.0.0",
				Methods: []*MethodConfig{
					{
						Name:        "GetUser",
						Retries:     "2",
						LoadBalance: "random",
						Weight:      200,
					},
					{
						Name:        "GetUser1",
						Retries:     "2",
						LoadBalance: "random",
						Weight:      200,
					},
				},
				exported: new(atomic.Bool),
			},
			"MockServiceNoRightProtocol": {
				InterfaceName: "com.MockService",
				Protocol:      "mock1",
				Registry:      "shanghai_reg1,shanghai_reg2,hangzhou_reg1,hangzhou_reg2,hangzhou_service_discovery_reg",
				Cluster:       "failover",
				Loadbalance:   "random",
				Retries:       "3",
				Group:         "huadong_idc",
				Version:       "1.0.0",
				Methods: []*MethodConfig{
					{
						Name:        "GetUser",
						Retries:     "2",
						LoadBalance: "random",
						Weight:      200,
					},
					{
						Name:        "GetUser1",
						Retries:     "2",
						LoadBalance: "random",
						Weight:      200,
					},
				},
				exported: new(atomic.Bool),
			},
		},

		Registries: map[string]*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",
			},
			"hangzhou_service_discovery_reg": {
				Protocol: "service-discovery",
				Params: map[string]string{
					"service_discovery": "mock_servicediscovery",
					"name_mapping":      "in-memory",
					"metadata":          "default",
				},
			},
		},

		Protocols: map[string]*ProtocolConfig{
			"mock": {
				Name: "mock",
				Ip:   "127.0.0.1",
				Port: "20000",
			},
		},
	}
}

func TestExport(t *testing.T) {
	doInitProvider()
	extension.SetProtocol("registry", GetProtocol)

	for i := range providerConfig.Services {
		service := providerConfig.Services[i]
		service.Implement(&MockService{})
		service.Protocols = providerConfig.Protocols
		err := service.Export()
		assert.Nil(t, err)
	}
	providerConfig = nil
}

func TestGetRandomPort(t *testing.T) {
	protocolConfigs := make([]*ProtocolConfig, 0, 3)

	ip := common.GetLocalIp()
	protocolConfigs = append(protocolConfigs, &ProtocolConfig{
		Ip: ip,
	})
	protocolConfigs = append(protocolConfigs, &ProtocolConfig{
		Ip: ip,
	})
	protocolConfigs = append(protocolConfigs, &ProtocolConfig{
		Ip: ip,
	})
	// assert.NoError(t, err)
	ports := getRandomPort(protocolConfigs)

	assert.Equal(t, ports.Len(), len(protocolConfigs))

	front := ports.Front()
	for {
		if front == nil {
			break
		}
		t.Logf("port:%v", front.Value)
		front = front.Next()
	}

	protocolConfigs = make([]*ProtocolConfig, 0, 3)
	ports = getRandomPort(protocolConfigs)
	assert.Equal(t, ports.Len(), len(protocolConfigs))
}
