package container

import (
	"LAPP_LF_MOM_BACKEND/web/models"
	"fmt"
	"reflect"
	"testing"
)

func TestFactory_Create_NullContext(t *testing.T) {

	factory := Factory(reflect.ValueOf(FactoryOfTestElement))

	_, err := factory.Create(nil)
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("会话上下文不能为空!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_Create_WithContext(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
	factory := Factory(reflect.ValueOf(FactoryOfTestServiceWithContext))

	instance, err := factory.Create(context)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
	impl, ok := (reflect.Value(instance)).Interface().(*TestServiceImplementWithContext)
	if !ok {
		t.Fatalf("实例类型错误!")
	}
	if impl.context == nil {
		t.Fatalf("会话上下文不能为空!")
	}
	if impl.context != context {
		t.Fatalf("会话上下文设置错误!")
	}
	if impl.context.user.Userid != userId {
		t.Fatalf("会话上下文内容错误!")
	}
}

func TestFactory_Create_WithContextUsingPointer(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
	factory := Factory(reflect.ValueOf(FactoryOfTestServiceImplementWithContext))

	instance, err := factory.Create(context)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
	impl, ok := (reflect.Value(instance)).Interface().(*TestServiceImplementWithContext)
	if !ok {
		t.Fatalf("实例类型错误!")
	}
	if impl.context == nil {
		t.Fatalf("会话上下文不能为空!")
	}
	if impl.context != context {
		t.Fatalf("会话上下文设置错误!")
	}
	if impl.context.user.Userid != userId {
		t.Fatalf("会话上下文内容错误!")
	}
}

func TestFactory_Create_WithContextUsingStruct(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
	factory := Factory(reflect.ValueOf(FactoryOfTestServiceImplementWithContextStruct))

	_, err = factory.Create(context)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_Create_UsingStructFactory(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
	factory := Factory(reflect.ValueOf(FactoryOfTestToString))

	_, err = factory.Create(context)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_Create_UsingIntFactory(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
	factory := Factory(reflect.ValueOf(FactoryOfInt))

	_, err = factory.Create(context)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_Create_WithFactoryOfNullInterface(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfNullTestService))

	_, err = factory.Create(context)
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("实际值不能是空接口!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_Create_WithFactoryOfNullPointer(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfNullTestServiceImplementWithContext))

	_, err = factory.Create(context)
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("实际值不能是空指针!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_Create_WithTooManyIn(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfTestWithTooManyInSetContext))

	_, err = factory.Create(context)
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("设置器参数数量不正确!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_Create_WithNoIn(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfTestWithNoInSetContext))

	_, err = factory.Create(context)
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("设置器参数数量不正确!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_Create_WithReturnValue(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfTestWithReturnValueSetContext))

	_, err = factory.Create(context)
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("设置器返回值数量不正确!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_Create_WithErrorIn(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfTestWithErrorInSetContext))

	_, err = factory.Create(context)
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("设置器类型不正确!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_SetReferences_WithEmptyMap(t *testing.T) {

	factory := Factory(reflect.ValueOf(FactoryOfTestServiceWithContext))
	instanceValue := reflect.Value(factory).Call(emptyParameters)[0]

	err := factory.setReferences(instanceValue, map[reflect.Type]reflect.Value{})
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_SetReferences_WithTooManyIn(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfTestWithTooManyInSetContext))
	instanceValue := reflect.Value(factory).Call(emptyParameters)[0]

	err = factory.setReferences(instanceValue, map[reflect.Type]reflect.Value{sessionContextType: reflect.ValueOf(context)})
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("设置器参数数量不正确!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_SetReferences_WithNoIn(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfTestWithNoInSetContext))
	instanceValue := reflect.Value(factory).Call(emptyParameters)[0]

	err = factory.setReferences(instanceValue, map[reflect.Type]reflect.Value{sessionContextType: reflect.ValueOf(context)})
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("设置器参数数量不正确!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_SetReferences_WithReturnValue(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfTestWithReturnValueSetContext))
	instanceValue := reflect.Value(factory).Call(emptyParameters)[0]

	err = factory.setReferences(instanceValue, map[reflect.Type]reflect.Value{sessionContextType: reflect.ValueOf(context)})
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("设置器返回值数量不正确!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}

func TestFactory_SetReferences_WithErrorIn(t *testing.T) {

	userId := "userId"
	user := &models.Usertab{Userid: userId}
	context, err := NewSessionContext(user, transactionHandlerFactoryMock)
	if err != nil {
		t.Fatalf("意外错误:%s", err.Error())
	}

	factory := Factory(reflect.ValueOf(FactoryOfTestWithErrorInSetContext))
	instanceValue := reflect.Value(factory).Call(emptyParameters)[0]

	err = factory.setReferences(instanceValue, map[reflect.Type]reflect.Value{sessionContextType: reflect.ValueOf(context)})
	if err == nil {
		t.Fatalf("意外的没有错误!")
	}
	if err.Error() != fmt.Sprintf("设置器类型不正确!") {
		t.Fatalf("意外错误:%s", err.Error())
	}
}
