package rpc

import (
	"LAPP_ACURA_MOM_BACKEND/container"
	"LAPP_ACURA_MOM_BACKEND/global"
	"LAPP_ACURA_MOM_BACKEND/web/middleware/jwts"
	"LAPP_ACURA_MOM_BACKEND/web/supports"
	"github.com/kataras/iris/v12"
	"reflect"
)

var DefaultMethodInvokerBuilder = &RouteBuilder{&MethodInvokerBuilder{&ValueParserBuilder{}, map[reflect.Type]valueParser{container.RequestContextType: keepValue}}}

type RouteBuilder struct {
	methodInvokerBuilder *MethodInvokerBuilder
}

func (builder *RouteBuilder) Build(callerFactory func(string, *global.User) (container.Caller, error), serviceMethodName string, methodType reflect.Type) (container.HttpMethod, string, container.Router, error) {

	router := func(context iris.Context) {
		var json interface{}
		var jsonArray []interface{}
		if context.GetContentLength() > 0 {
			if nil != context.ReadJSON(&json) {
				supports.Error(context, iris.StatusBadRequest, "JSON解析失败!", nil)
				return
			}
			if json != nil {
				if jsonObject, ok := json.([]interface{}); !ok {
					supports.Error(context, iris.StatusBadRequest, "JSON解析失败!", nil)
					return
				} else {
					jsonArray = jsonObject
				}
			}
		}
		user, signature, ok := jwts.ParseTokenAndSignature(context)
		if !ok {
			supports.Error(context, iris.StatusBadRequest, supports.ParseParamsFailur, nil)
			return
		}
		requestContext, err := container.NewRequestContext("rc", context)
		if err != nil {
			supports.Error(context, iris.StatusInternalServerError, err.Error(), nil)
			return
		}
		jsonArray = append([]interface{}{requestContext}, jsonArray...)
		caller, err := callerFactory(user.UserId+signature, user)
		if err != nil {
			supports.Error(context, iris.StatusInternalServerError, err.Error(), nil)
			return
		}
		methodInvoker, err := builder.methodInvokerBuilder.buildMethodInvoker(serviceMethodName, methodType, caller)
		if err != nil {
			supports.Error(context, iris.StatusInternalServerError, err.Error(), nil)
			return
		}
		defer func() {
			if err := recover(); err != nil {
				supports.Error(context, iris.StatusInternalServerError, "内部错误", nil)
				return
			}
		}()
		if result, err := methodInvoker.Process(jsonArray); err != nil {
			supports.Error(context, iris.StatusInternalServerError, err.Error(), nil)
		} else {
			supports.Ok(context, supports.OptionSuccess, result)
		}
	}
	return container.HttpPost, "", router, nil
}
