// Package router ...
//
// Description : router ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-01-27 19:42
package router

import (
	"git.zhangdeman.cn/zhangdeman/exception"
	"git.zhangdeman.cn/zhangdeman/gin/define"
	"git.zhangdeman.cn/zhangdeman/gin/request"
	"git.zhangdeman.cn/zhangdeman/gin/response"
	"github.com/gin-gonic/gin"
	"reflect"
	"sync"
)

// RequestHandler 获取请求处理方法
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 19:44 2025/1/27
func RequestHandler(uriCfg UriConfig) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		var (
			err error
			ok  bool
			e   exception.IException
		)

		var formParam reflect.Value
		if uriCfg.FormDataType.Kind() == reflect.Ptr {
			formParam = reflect.New(uriCfg.FormDataType.Elem())
		} else {
			// 表单解析
			formParam = reflect.New(uriCfg.FormDataType)
		}
		formValue := formParam.Interface()
		if err = request.Form.Parse(ctx, formValue); nil != err {
			// 格式化验证错误的信息
			err = GetValidateErr(formValue, err)
			e = exception.NewFromError(400, err)
			response.SendWithException(ctx, e, nil)
			ctx.Abort()
			return
		}

		// 初始化响应之后logic
		logicAfterResponse := &define.LogicAfterResponse{
			SuccessHookFuncList: make([]func(), 0),
			FailureHookFuncList: make([]func(), 0),
			Lock:                &sync.RWMutex{},
		}
		// 此处暴露出去,是为了使用方可以获取到对应数据
		ctx.Set(define.LogicAfterResponseKey, logicAfterResponse)

		// 执行逻辑
		inputValue := reflect.ValueOf(formValue)
		if uriCfg.FormDataType.Kind() != reflect.Ptr {
			inputValue = inputValue.Elem()
		}
		resList := uriCfg.ApiLogicFunc.Func.Call([]reflect.Value{uriCfg.ApiStructValue, reflect.ValueOf(ctx), inputValue})
		if resList[1].IsNil() {
			// 请求成功
			response.Success(ctx, resList[0].Interface())
			// 执行成功之后的逻辑
			for _, item := range logicAfterResponse.SuccessHookFuncList {
				if item != nil {
					item()
				}
			}
			return
		}
		// 请求失败
		if e, ok = resList[1].Interface().(exception.IException); ok {
			// 本身就是exception.IException
		} else if err, ok = resList[1].Interface().(error); ok {
			e = exception.NewFromError(-1, err)
		} else {
			e = exception.NewWithCodeAndData(-1, map[string]any{
				"err": resList[1].Interface(),
			})
		}
		response.SendWithException(ctx, e, nil)
		// 执行失败之后的逻辑
		for _, item := range logicAfterResponse.FailureHookFuncList {
			if item != nil {
				item()
			}
		}
		return
	}
}