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

import (
	"context"
	"fmt"
	"reflect"
	"testing"
)

import (
	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/protocol"
	"github.com/apache/dubbo-go/protocol/dubbo/hessian2"
	"github.com/apache/dubbo-go/protocol/invocation"
)

type TestService struct {
	MethodOne   func(context.Context, int, bool, *interface{}) error
	MethodTwo   func([]interface{}) error
	MethodThree func(int, bool) (interface{}, error)
	MethodFour  func(int, bool) (*interface{}, error) `dubbo:"methodFour"`
	MethodFive  func() error
	MethodSix   func(context.Context, string) (interface{}, error)
	Echo        func(interface{}, *interface{}) error
}

func (s *TestService) Reference() string {
	return "com.test.Path"
}

type TestServiceInt int

func (s *TestServiceInt) Reference() string {
	return "com.test.TestServiceInt"
}

func TestProxyImplement(t *testing.T) {

	invoker := protocol.NewBaseInvoker(&common.URL{})
	p := NewProxy(invoker, nil, map[string]string{constant.ASYNC_KEY: "false"})
	s := &TestService{}
	p.Implement(s)

	err := p.Get().(*TestService).MethodOne(nil, 0, false, nil)
	assert.NoError(t, err)

	err = p.Get().(*TestService).MethodTwo(nil)
	assert.NoError(t, err)
	ret, err := p.Get().(*TestService).MethodThree(0, false)
	assert.NoError(t, err)
	assert.Nil(t, ret) // ret is nil, because it doesn't be injection yet

	ret2, err := p.Get().(*TestService).MethodFour(0, false)
	assert.NoError(t, err)
	assert.Equal(t, "*interface {}", reflect.TypeOf(ret2).String())
	err = p.Get().(*TestService).Echo(nil, nil)
	assert.NoError(t, err)

	err = p.Get().(*TestService).MethodFive()
	assert.NoError(t, err)

	// inherit & lowercase
	p.rpc = nil
	type S1 struct {
		TestService
		methodOne func(context.Context, interface{}, *struct{}) error
	}
	s1 := &S1{TestService: *s, methodOne: func(_ context.Context, _ interface{}, _ *struct{}) error {
		return perrors.New("errors")
	}}
	p.Implement(s1)
	err = s1.MethodOne(nil, 0, false, nil)
	assert.NoError(t, err)
	err = s1.methodOne(nil, nil, nil)
	assert.EqualError(t, err, "errors")

	// no struct
	p.rpc = nil
	it := TestServiceInt(1)
	p.Implement(&it)
	assert.Nil(t, p.rpc)

	// return number
	p.rpc = nil
	type S2 struct {
		TestService
		MethodOne func([]interface{}) (*struct{}, int, error)
	}
	s2 := &S2{TestService: *s}
	p.Implement(s2)
	assert.Nil(t, s2.MethodOne)

	// returns type
	p.rpc = nil
	type S3 struct {
		TestService
		MethodOne func(context.Context, []interface{}, *struct{}) interface{}
	}
	s3 := &S3{TestService: *s}
	p.Implement(s3)
	assert.Nil(t, s3.MethodOne)

}

func TestProxyImplementForContext(t *testing.T) {
	invoker := &TestProxyInvoker{
		BaseInvoker: *protocol.NewBaseInvoker(&common.URL{}),
	}
	p := NewProxy(invoker, nil, map[string]string{constant.ASYNC_KEY: "false"})
	s := &TestService{}
	p.Implement(s)
	attachments1 := make(map[string]interface{}, 4)
	attachments1["k1"] = "v1"
	attachments1["k2"] = "v2"
	context := context.WithValue(context.Background(), constant.AttachmentKey, attachments1)
	r, err := p.Get().(*TestService).MethodSix(context, "xxx")
	v1 := r.(map[string]interface{})
	assert.NoError(t, err)
	assert.Equal(t, v1["TestProxyInvoker"], "TestProxyInvokerValue")
}

type TestProxyInvoker struct {
	protocol.BaseInvoker
}

func (bi *TestProxyInvoker) Invoke(_ context.Context, inv protocol.Invocation) protocol.Result {
	rpcInv := inv.(*invocation.RPCInvocation)
	mapV := inv.Attachments()
	mapV["TestProxyInvoker"] = "TestProxyInvokerValue"
	if err := hessian2.ReflectResponse(mapV, rpcInv.Reply()); err != nil {
		fmt.Printf("hessian2.ReflectResponse(mapV:%v) = error:%v", mapV, err)
	}

	return &protocol.RPCResult{
		Rest: inv.Arguments(),
	}
}
