/*
 * 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 jsonrpc

import (
	"context"
	"strings"
	"testing"
	"time"
)

import (
	"github.com/opentracing/opentracing-go"
	perrors "github.com/pkg/errors"
	"github.com/stretchr/testify/assert"
)

import (
	"github.com/apache/dubbo-go/common"
	"github.com/apache/dubbo-go/common/constant"
	"github.com/apache/dubbo-go/common/proxy/proxy_factory"
	"github.com/apache/dubbo-go/protocol"
)

type (
	User struct {
		Id   string `json:"id"`
		Name string `json:"name"`
	}

	UserProvider struct {
		//user map[string]User
	}
)

const (
	mockJsonCommonUrl = "jsonrpc://127.0.0.1:20001/com.ikurento.user.UserProvider?anyhost=true&" +
		"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&" +
		"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&" +
		"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&" +
		"side=provider&timeout=3000&timestamp=1556509797245&bean.name=UserProvider"
)

func TestHTTPClientCall(t *testing.T) {

	methods, err := common.ServiceMap.Register("com.ikurento.user.UserProvider", "jsonrpc", "", "", &UserProvider{})
	assert.NoError(t, err)
	assert.Equal(t, "GetUser,GetUser0,GetUser1,GetUser2,GetUser3,GetUser4", methods)

	// Export
	proto := GetProtocol()
	url, err := common.NewURL(mockJsonCommonUrl)
	assert.NoError(t, err)
	proto.Export(&proxy_factory.ProxyInvoker{
		BaseInvoker: *protocol.NewBaseInvoker(url),
	})
	time.Sleep(time.Second * 2)

	client := NewHTTPClient(&HTTPOptions{})

	// call GetUser
	ctx := context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
		"X-Proxy-ID": "dubbogo",
		"X-Services": url.Path,
		"X-Method":   "GetUser",
	})

	req := client.NewRequest(url, "GetUser", []interface{}{"1", "username"})
	reply := &User{}
	err = client.Call(ctx, url, req, reply)
	assert.NoError(t, err)
	assert.Equal(t, "1", reply.Id)
	assert.Equal(t, "username", reply.Name)

	// call GetUser0
	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
		"X-Proxy-ID": "dubbogo",
		"X-Services": url.Path,
		"X-Method":   "GetUser0",
	})
	req = client.NewRequest(url, "GetUser0", []interface{}{"1", nil, "username"})
	reply = &User{}
	err = client.Call(ctx, url, req, reply)
	assert.NoError(t, err)
	assert.Equal(t, "1", reply.Id)
	assert.Equal(t, "username", reply.Name)

	// call GetUser1
	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
		"X-Proxy-ID": "dubbogo",
		"X-Services": url.Path,
		"X-Method":   "GetUser1",
	})
	req = client.NewRequest(url, "GetUser1", []interface{}{})
	reply = &User{}
	err = client.Call(ctx, url, req, reply)
	assert.True(t, strings.Contains(err.Error(), "500 Internal Server Error"))
	assert.True(t, strings.Contains(err.Error(), "\\\"result\\\":{},\\\"error\\\":{\\\"code\\\":-32000,\\\"message\\\":\\\"error\\\"}"))

	// call GetUser2
	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
		"X-Proxy-ID": "dubbogo",
		"X-Services": url.Path,
		"X-Method":   "GetUser2",
	})
	req = client.NewRequest(url, "GetUser2", []interface{}{"1", "username"})
	reply1 := []User{}
	err = client.Call(ctx, url, req, &reply1)
	assert.NoError(t, err)
	assert.Equal(t, User{Id: "1", Name: "username"}, reply1[0])

	// call GetUser3
	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
		"X-Proxy-ID": "dubbogo",
		"X-Services": url.Path,
		"X-Method":   "GetUser3",
	})
	req = client.NewRequest(url, "GetUser3", []interface{}{"1", "username"})
	reply1 = []User{}
	err = client.Call(ctx, url, req, &reply1)
	assert.NoError(t, err)
	assert.Equal(t, User{Id: "1", Name: "username"}, reply1[0])

	// call GetUser4
	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
		"X-Proxy-ID": "dubbogo",
		"X-Services": url.Path,
		"X-Method":   "GetUser4",
	})
	req = client.NewRequest(url, "GetUser4", []interface{}{0})
	reply = &User{}
	err = client.Call(ctx, url, req, reply)
	assert.NoError(t, err)
	assert.Equal(t, &User{Id: "", Name: ""}, reply)

	ctx = context.WithValue(context.Background(), constant.DUBBOGO_CTX_KEY, map[string]string{
		"X-Proxy-ID": "dubbogo",
		"X-Services": url.Path,
		"X-Method":   "GetUser4",
	})

	span := opentracing.StartSpan("Test-Inject-Tracing-ID")
	ctx = opentracing.ContextWithSpan(ctx, span)

	req = client.NewRequest(url, "GetUser4", []interface{}{1})
	reply = &User{}
	err = client.Call(ctx, url, req, reply)
	assert.NoError(t, err)
	assert.Equal(t, &User{Id: "1", Name: ""}, reply)

	// destroy
	proto.Destroy()

}

func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User) error {
	rsp.Id = req[0].(string)
	rsp.Name = req[1].(string)
	return nil
}

func (u *UserProvider) GetUser0(id string, k *User, name string) (User, error) {
	return User{Id: id, Name: name}, nil
}

func (u *UserProvider) GetUser1() error {
	return perrors.New("error")
}

func (u *UserProvider) GetUser2(ctx context.Context, req []interface{}, rsp *[]User) error {
	*rsp = append(*rsp, User{Id: req[0].(string), Name: req[1].(string)})
	return nil
}

func (u *UserProvider) GetUser3(ctx context.Context, req []interface{}) ([]User, error) {
	return []User{{Id: req[0].(string), Name: req[1].(string)}}, nil
}

func (u *UserProvider) GetUser4(id float64) (*User, error) {
	if id == 0 {
		return nil, nil
	}
	return &User{Id: "1"}, nil
}

func (u *UserProvider) Reference() string {
	return "UserProvider"
}
