package dapi

import (
	"epur-pay/cache"
	"epur-pay/model"
	"epur-pay/pkg/limit"
	"epur-pay/pkg/logger"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"reflect"
	"runtime"
	"time"
)

var Cf *Config

func New() {
	Cf = &Config{}
}

func (p *Config) SetApiBefore(f func(a *ApiBase) error) *Config {
	p.ApiBefore = f
	return p
}

func (p *Config) SetApiAuth(f func(a *ApiBase) error) *Config {
	p.ApiAuth = f
	return p
}

func (p *Config) SetApiAfter(f func(a *ApiBase) error) *Config {
	p.ApiAfter = f
	return p
}

//func (p *Config) SetApiGetLang(f func(Lang, Key string) string) *Config {
//	p.ApiGetLang = f
//	return p
//}

func (p *Config) SetRefreshCache(f func(Key string) error) *Config {
	p.ApiRefreshCache = f
	return p
}

//func (p *Config) SetKKStop(f *bool) *Config {
//	p.KKStop = f
//	return p
//}
//
//func (p *Config) SetProjectInitStatus(f *bool) *Config {
//	p.ProjectInitStatus = f
//	return p
//}

type Config struct {
	ApiBefore func(a *ApiBase) error
	//ApiRun            func() error
	ApiAfter func(a *ApiBase) error
	ApiAuth  func(a *ApiBase) error //鉴权
	//ApiGetLang        func(Lang, Key string) string
	ApiRefreshCache func(Key string) error // 刷新项目缓存
	//KKStop            *bool
	//ProjectInitStatus *bool //项目是否初始化完成
}

type InParams struct {
	IsTransaction      bool // 是否开启事务
	IsTicket           bool // 是否校验Token获取用户校验用户合法性
	IsForUpdate        bool // 是否加用户锁
	IsTicketSkip       bool // 有就获取用户 没有也不报错
	IsErrors           bool // 是否多条错误返回
	IsCertified        bool // 是否判断认证
	IsNoCheckBlackList bool // 是否不校验黑名单
	IsKKTrade          bool
	IsSaveLog          bool
	IsSkipErrorSaveLog bool
	SaveEvent          string
	IsAgentAction      bool   // 是否允许代理操作 true-是 false-否
	IsSuperOnly        bool   // 是否只允许Super操作
	Permission         string // 权限标识
	LimitRouterRuleKey string
	LimitRouterRule    *limit.LimitOpt
}

type ApiBase struct {
	C                  *gin.Context
	Ts                 *gorm.DB
	InParams           *InParams
	IsCustomResponse   bool           // 是否自定义返回
	Response           *Response      // 返回结构
	CustomResponse     *interface{}   // 自定义返回结构
	User               *model.User    // 用户结构
	Token              string         // 鉴权Token
	Local              *time.Location // 时区
	Site               string         // 站点类型: h5App h5Pc h5Admin
	Currency           string         // 币种
	Lang               string         // 语言
	Error              error          // 错误信息
	body               interface{}    // 请求的body数据
	paramNum           int            // 函数参数数量
	funcValue          reflect.Value  // 函数指针
	Limit              int            // 当前页数显示条数
	Offset             int            // 跳过条数
	AfterCallback      func()         // 后续处理
	AfterCallbackDelay int64          // 延迟时间
	Log                *model.Log
}

func ApiDecorator(handlerFunc interface{}, InParams *InParams) func(*gin.Context) {

	paramNum := reflect.TypeOf(handlerFunc).NumIn()
	funcValue := reflect.ValueOf(handlerFunc)
	funcType := reflect.TypeOf(handlerFunc)

	if funcType.Kind() != reflect.Func {
		panic("the route handlerFunc must be a function")
	}

	if len(InParams.LimitRouterRuleKey) > 0 && InParams.LimitRouterRule != nil {
		cache.Global.LimitRouter.Rule.Rules[InParams.LimitRouterRuleKey] = InParams.LimitRouterRule
	}

	return func(c *gin.Context) {

		a := &ApiBase{Response: &Response{}}
		a.InParams = InParams
		a.paramNum = paramNum
		a.funcValue = funcValue
		a.C = c

		if paramNum > 1 {
			a.body = reflect.New(funcType.In(1).Elem()).Interface()
		}
		apiProxy(a)
	}
}

func apiProxy(a *ApiBase) {
	defer func() {
		err := recover()
		if err != nil {
			buf := make([]byte, 1<<16)
			runtime.Stack(buf, true)
			e := reflect.ValueOf(err)
			logger.ErrorLogger.Errorln(e.String(), string(buf))
			_ = a.ReturnErrorResponse(ServerError, a.Translate("sys_error"))
		}

		a.freeTrade()
		a.saveLog()
		a.response()
	}()
	a.Error = a.apiMain()
}